我正在设置一个监控脚本,当数据包失败时,该脚本将ping IP并发送电子邮件。我决定使用Test-Connection
。下面是一个示例代码:
Code1
$IPList = @("192.168.0.1","172.217.161.15")
Test-Connection -ComputerName $IPList -BufferSize 4 -Count 1 -AsJob -ErrorAction Stop
Get-Job | Wait-Job | Receive-Job
所以我得到的结果是:
Source Destination IPV4Address IPV6Address Bytes Time(ms)
------ ----------- ----------- ----------- ----- --------
BLR-AA200906 172.217.161.15 4 55
BLR-AA200906 192.168.0.1 4
192系列IP应该会抛出一个错误。您可以看到Time(ms)
列为空。
Code2
$IPList = @("192.168.0.1","172.217.161.15")
foreach ($IP in $IPList)
{
Start-job -ScriptBlock {Test-Connection -ComputerName $Args[0] -BufferSize 4 -Count 1 -ErrorAction Stop} -ArgumentList $IP
}
Get-Job | Wait-Job | Receive-Job
如果我这样做,它会抛出一个错误,我可以很容易地捕捉
Testing connection to computer '192.168.0.1' failed: Error due to lack of resources
+ CategoryInfo : ResourceUnavailable: (192.168.0.1:String) [Test-Connection], PingException
+ FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand
+ PSComputerName : localhost
问题
这就引出了我的问题。如何接收/捕获Code1中抛出的错误消息?不同的是,我使用的是-AsJob
,它比在foreach
循环中启动作业效率高得多。
PS版本为5.1
我没有特定的解决方案,但这就是问题的原因:
-AsJob
参数创建WMI作业,而Start-Job
创建CIM作业。
WMI作业每个都有自己的实例,CIM作业在当前Powershell实例中运行。因此,WMI作业使用当前会话创建和销毁实例不需要额外的时间,这可能非常昂贵。
WMI作业通常与Powershell有点分离。它们似乎没有一个"宿主"外壳可以转录。这就是Powershell的二元性可能会变得有点混乱的地方。
不幸的是,在这种情况下,这意味着您完全依赖于实现Powershell的事件处理程序的Test-Connection
cmdlet,但事实并非如此,因为作业状态总是记录为"Completed"。您再也无法通过简单地将CIM作业自己的shell转储到输出流来恢复CIM作业所带来的"兼容性"。
Start-Job -ScriptBlock {Write-Host "This is not real output."} | Wait-Job | Receive-Job
PS> This is not real output.
因此,在您的情况下,如果必须使用-AsJob
,那么您能做的最好的事情就是监视$error
。(据我所知。(
重要的是要区分您的代码示例正在做不同的事情,Code1正在启动一个作业并运行x个测试连接。Code2正在旋转x个作业,每个作业测试1个连接。
我不知道有什么方法可以用-asjob从测试连接中消除错误,但另一种方法是使用statuscode属性。11010
是Error due to lack of resources
的状态码,当测试连接没有收到来自主机的响应时,即Request Timed Out
。
使用状态代码的缺点是,您需要转换状态代码。
$IPList = @("192.168.254.1","172.217.161.15")
$StatusCodes = @{
[uint32]0 = 'Success'
[uint32]11001 = 'Buffer Too Small'
[uint32]11002 = 'Destination Net Unreachable'
[uint32]11003 = 'Destination Host Unreachable'
[uint32]11004 = 'Destination Protocol Unreachable'
[uint32]11005 = 'Destination Port Unreachable'
[uint32]11006 = 'No Resources'
[uint32]11007 = 'Bad Option'
[uint32]11008 = 'Hardware Error'
[uint32]11009 = 'Packet Too Big'
[uint32]11010 = 'Request Timed Out'
[uint32]11011 = 'Bad Request'
[uint32]11012 = 'Bad Route'
[uint32]11013 = 'TimeToLive Expired Transit'
[uint32]11014 = 'TimeToLive Expired Reassembly'
[uint32]11015 = 'Parameter Problem'
[uint32]11016 = 'Source Quench'
[uint32]11017 = 'Option Too Big'
[uint32]11018 = 'Bad Destination'
[uint32]11032 = 'Negotiating IPSEC'
[uint32]11050 = 'General Failure'
}
Test-Connection -ComputerName $IPList -BufferSize 4 -Count 1 -AsJob
Get-Job | Wait-Job | Receive-Job | ft Address,IPV4Address,IPV6Address,Buffersize,ResponseTime,@{n="Status";e={$StatusCodes[$_.statuscode]}}
这给出了以下输出
Address IPV4Address IPV6Address Buffersize ResponseTime Status
------- ----------- ----------- ---------- ------------ ------
172.217.161.15 172.217.161.15 4 381 Success
192.168.254.1 4 Request Timed Out
我很感激这不会给你错误消息,但你可以检查每个请求的状态,并用它来执行你本可以通过捕捉错误来完成的业务逻辑。
参考
IcmpSendEcho2失败,WSA_QOS_ADMISSION_FAILURE和ERROR_NOACCESS 失败
https://learn.microsoft.com/en-gb/windows/desktop/api/ipexport/ns-ipexport-icmp_echo_reply
Powershell-由于缺乏资源,测试连接失败