Powershell 调用命令并返回结果或错误

Powershell invoke command and getting result or error back

我有一个 powershell 脚本,如下所示。

$credential = Get-Credential
$server_list = @('server1','server2')
$script = "[System.Net.Dns]::GetHostName()"
foreach ($server_name in $server_list) {
    
    $result = invoke-command -ComputerName $server_name -ScriptBlock { [System.Net.Dns]::GetHostName() }
    write-output "Remote command execution result is $result"
}

有什么问题?

在下面的示例中,如果由于某种原因无法访问服务器或遇到拒绝访问错误,则不会填充结果的值。 $result 的值仅在成功执行时才会填充。

有时,我会收到以下错误。

Connecting to remote server server1 failed with the following error message: WinRM cannot process the request. The following error occured whilst using kerberos authentication: cannot find the computer server1. Verify that the computer exists on the network and that the name provided is spelled correctly.

现在,我想要实现的是,对于每台服务器,使用 [System.Net.Dns]::GetHostName() 或任何其他方式获取主机名、当前时间和 powershell 版本以及任何错误消息。将其存储在自定义对象等中,并将其 return 作为脚本块的一部分。这样,当我收到每个服务器的结果值时,我可以将结果加载到数据库中并分析哪些服务器遇到错误等。

我查看了 How to capture the Return Value of a ScriptBlock invoked with Powershell's Invoke-Command,这是一个很好的参考,但他们在那里所做的是一个 ping,在我的例子中,ping 并没有真正回答所使用的凭证是否有效等问题。

Invoke-Command 具有“通用参数”,如“ErrorVariable”。因此,您可以使用“-ErrorVariable ErrorVariableName”将错误对象分配给它。 然后您可以检查 ErrorVariableName 是否为 null 并对其进行处理。像这样:

$creds = Get-Credential
$server_list = @('server1','server2')
[System.Collections.Generic.List[pscustomobject]]$Output = @();

foreach ($server_name in $server_list) {
    $result = invoke-command -ComputerName $server_name -ScriptBlock { [System.Net.Dns]::GetHostName() } -ErrorVariable ErrVar -Credential $creds

    if ($ErrVar)
    {
        $Output.Add([PSCustomObject]@{
            Server = $server_name
            IsError = $true
            Result = $ErrVar
        })
    } 
    else 
    {
        $Output.Add([PSCustomObject]@{
            Server = $server_name
            IsError = $false
            Result = $result
        })
    }
}

# do something with $Output

此外,查看错误变量本身,它有一些属性,如 ErrorCategory、StackTrace 等...如果您不想要完整的 StackTrace,只需要 CategoryInfo。

或者,您可以使用检查 try{} catch{}。由于 Invoke-Command 不是因错误而终止,因此您需要将 ErrorActionPreference 变量定义为 Stop,或使用 -ErrorAction Stop 使语句终止。

微软参考资料:

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_commonparameters?view=powershell-7.2 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-7.2