Server Service Status Check Using Pester

This topic contains 3 replies, has 2 voices, and was last updated by  Naw Awn 2 weeks, 6 days ago.

  • Author
    Posts
  • #80726

    Naw Awn
    Participant

    Hello,

    I have a scenario where I need to check if necessary services are up and running after the servers reboot. They are not just one or two servers that I can check with Get-Service cmdlet and go through the service lists but they are hundreds. If you are a GUI admin then this is not being possible to check them within (let's say) half an hour. So I went through a few options to collect the services that need checking. My options were to keep those services in xml, JSON or csv file. After running the following scripts, I compare the output file size.

    Get-services -cn $Computer | Where{($_.Status -eq "Running") -and ($_.StartType -eq "Automatic")} | 
            Sort Name | select Name,Status,StartType | Export-Csv c:\temp\Services\$Computer.csv -notype
    
    Get-services -cn $Computer | Where{($_.Status -eq "Running") -and ($_.StartType -eq "Automatic")} | 
            Sort Name | select Name,Status,StartType | ConvertTo-JSON | Out-File c:\temp\Services\$Computer.JSON
    
    Get-services -cn $Computer | Where{($_.Status -eq "Running") -and ($_.StartType -eq "Automatic")} | 
            Sort Name | select Name,Status,StartType | export-clixml c:\temp\Services\$Computer.xml
    

    .csv files are the smallest. So I choose csv format and collect all those service details when the machines are running in a stable state. I then wrote the Pester script below. When writing the script I have a few questions come up in my mind.
    1. Is Pester the right too for such testing (I could just write the PowerShell script which would do the same thing). It does work but I am not that convinced
    2. Is there any way to replace this part – If (!($PingResult)) {Continue}, maybe in a Pester way?

    Could someone enlighten me?

    $CsvPath= "C:\temp\Services"
    
    Describe 'Service status check'{
    
        Context 'Csv Files Check'{
            $Files = (Get-ChildItem $CsvPath\*.csv)
            Foreach($file in $Files){
                It "$file Size should be greater than 0KB"{
                    $file.length | Should BeGreaterThan 0
                }
            }
        }
    
        Context 'Server Check'{
            Foreach($Computer in $Files.basename){
                $PingResult = (Test-Connection $Computer -Count 1 -Quiet)
                It "$Computer should be up and runing"{
                    $PingResult | Should Be $true
                    #Test-Connection $Computer -Count 2 -Quiet | Should Be $true
                }        
            
                If (!($PingResult)) {Continue}
                Context "$Computer Service Check"{
                    $Services = (Import-Csv $CsvPath\$Computer.csv)     
                    Foreach($Service in $Services){
                        It "$Computer $Service should be running"{
                            (Get-Service -ComputerName $Computer -Name $Service.Name).Status | Should Be 'Running'
                        }
                    }
                }
            }
        }
    }
    #Invoke-Pester .\ServicesCheck.tests.ps1
    

    This is my first post so go easy on me 🙂
    Thanks

  • #80729

    Adam Bertram
    Moderator

    Your logic is solid. You could speed it up by using background jobs or parallel runspaces but if this is good enough then this works just as well.

    You could make it a little cleaner by doing something like this:

    $CsvPath= "C:\temp\Services"
    
    Describe 'Service status check'{
    
    	Context 'Csv Files Check'{
    		$Files = (Get-ChildItem $CsvPath\*.csv)
    		Foreach($file in $Files){
    			It "$file Size should be greater than 0KB"{
    				$file.length | Should BeGreaterThan 0
    			}
    			it 'should have more than 1 row' {
    				(Import-Csv -path $file.FullName).Count | should BeGreaterThan 0
    			}
    		}
    	}
    
    	Context 'Server Check'{
    		Foreach($Computer in $Files.basename){
    			$PingResult = (Test-Connection $Computer -Count 1 -Quiet)
    			$Services = (Import-Csv $CsvPath\$Computer.csv)
    
    			It "$Computer should be up and runing"{
    				$PingResult | Should Be $true
    			}
    
    			Foreach($Service in $Services){
    				$itParams = @{
    					name = "$Computer $Service should be running"
    				}
    				if (-not $PingResult) {
    					$itParams.test = { (Get-Service -ComputerName $Computer -Name $Service.Name).Status | Should Be 'Running' }
    				} else {
    					$itParams.test = { Set-TestInconclusive }
    				}
    				it @itParams
    			}
    		}
    	}
    }
    #Invoke-Pester .\ServicesCheck.tests.ps1
    
  • #80737

    Naw Awn
    Participant

    Thanks Adam. Believe it or not I wrote this script after watching your Testing PowerShell with Pester on mva over the weekend.
    Your answer then leads me to another question, does Pester support workflow foreach -parallel (){}?
    If it does I will go down to that route.

  • #80815

    Naw Awn
    Participant

    This is brilliant! I am loving it. I have to change this bit to correct the logic.
    if (-not $PingResult)
    Thanks again Adam. Your input is much appreciated.

    $CsvPath= "C:\temp\Services"
    
    Describe 'Service status check'{
    
    	Context 'Csv Files Check'{
    		$Files = (Get-ChildItem $CsvPath\*.csv)
    		Foreach($file in $Files){
    			It "$file Size should be greater than 0KB"{
    				$file.length | Should BeGreaterThan 0
    			}
    			it 'should have more than 1 row' {
    				(Import-Csv -path $file.FullName).Count | should BeGreaterThan 0
    			}
    		}
    	}
    
    	Context 'Server Check'{
    		Foreach($Computer in $Files.basename){
    			$PingResult = (Test-Connection $Computer -Count 1 -Quiet)
    			$Services = (Import-Csv $CsvPath\$Computer.csv)
    
    			It "$Computer should be up and runing"{
    				$PingResult | Should Be $true
    			}
    
    			Foreach($Service in $Services){
    				$itParams = @{
    					name = "$Computer $Service should be running"
    				}
    				if ($PingResult) {
    					$itParams.test = { (Get-Service -ComputerName $Computer -Name $Service.Name).Status | Should Be 'Running' }
    				} else {
    					$itParams.test = { Set-TestInconclusive }
    				}
    				it @itParams
    			}
    		}
    	}
    }
    #Invoke-Pester .\ServicesCheck.tests.ps1
    

    This script run 3s faster than the original script over one hundred machines.

You must be logged in to reply to this topic.