Search code examples
powershell

Script to Check Services on Remote Servers Not Working


I'm trying to get the script below to do the following.

  1. Ping each server making sure it's up. (Working)
  2. Check multiple services on multiple servers to make sure they are running (Working...Kinda). For # 2 the script executes and seems to run successful but always returns that the service is not running although it is. I pretty new to PS so any guidance is appreciated.
$Servers = "Server1", "Server2"
$services = "Service1", "Service2"
$Cred = Get-Credential
foreach ($Server in $Servers)
    {
    $ip = $Server.Split(" - ")[0]
    if (Test-Connection  $ip -Count 1 -ErrorAction SilentlyContinue){
        Write-Host "$ip is up"
        }
    else{
        Write-Host "$ip is down"
        }
    }
foreach ($server in $servers) {
        Write-Host "Checking services on $server..."
        foreach ($service in $services) {
            
            $status = Invoke-Command -ComputerName $servers -Credential $Cred -ScriptBlock {
                Get-Service -Name $services -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Status
            }
                if ($status -eq "Running") {
                Write-Host "$service is running on $server"
            } else {
                Write-Host "$service is not running on $server"
            }
        }
    }

I have tried multiple ways to get this to work, but unfortunately nothing has.


Solution

  • When you do:

    $status = Invoke-Command -ComputerName $servers -Credential $Cred -ScriptBlock {
        Get-Service -Name $services ....
    }
    

    $services isn't defined in the context of your Invoke-Command, you should use either $using: or -ArgumentList to pass-in the values to the remote scope.

    I'd personally also discard the ping tests in your code, a server responding to icmp requests isn't an indication that you can connect to them via Invoke-Command, this cmdlet can also handle parallel invocation, meaning that the loop on $servers isn't required.

    In summary you could do this:

    Invoke-Command -ComputerName $servers -Credential $Cred -ScriptBlock {
        Get-Service -Name $using:services -ErrorAction SilentlyContinue |
            Select-Object Name, Status
    } -ErrorAction SilentlyContinue -ErrorVariable failedToConnect |
        Select-Object PSComputerName, Name, Status
    

    And then if you wanted to check which servers you couldn't connect, you can check the variable used in -ErrorVariable:

    # Gives you a list of all servers
    $failedToConnect.TargetObject