以下功能将使用PingRange 1 254
ping我的子网以检查IP:
function PingRange ($from, $to) {
$from..$to | % {"192.168.0.$($_): $(Test-Connection -BufferSize 2 -TTL 5 -ComputerName 192.168.0.$($_ ) -quiet -count 1)"}
}
但是,这很慢,所以我想知道是否可以同时对它们全部执行ping操作,然后收集结果。我想这将意味着:
在每个Test-Connection上使用Start-Job(我可以做,那部分很容易)。
等待所有人完成。
仅收集ping成功结果并将其排序。
function PingRange $from $to {
$from..$to | % {Start-Job { "192.168.0.$($_): $(Test-Connection -BufferSize 2 -TTL 5 -ComputerName 192.168.0.$($_ ) -quiet -count 1)"} }
Wait-Job *some test to check if all jobs are complete*
Receive-Job some way to get each result, discard all failures, then sort and output to screen
}
是否有一种简便的方法来完成等待工作,该等待工作将等待all生成的作业完成?
接收信息似乎也很棘手,当我尝试接收信息时,我总是会从Receive-Job中得到任何东西(通常是一个讨厌的错误)。希望有更多关于PowerShell Jobs的专家知道如何轻松获得这些结果?
在PowerShell v7 +中,您将能够使用ForEach-Object -Parallel
,通过使用不同的threads在parallel中运行命令,可以大大简化您的功能。 :
ForEach-Object -Parallel
function PingRange ($from, $to) {
$from..$to | ForEach-Object -Parallel {
"192.168.0.$_`: $(Test-Connection -BufferSize 2 -TTL 5 -ComputerName 192.168.0.$_ -quiet -count 1)"
} -ThrottleLimit ($to - $from + 1) 2>$null -ErrorVariable err | Sort-Object
}
默认为-ThrottleLimit
,这意味着最多有5个命令并行运行,其他的<>,直到前一个命令完成后,池中的一个线程再次可用。 这里,我选择允许
5
以获取指导。2>$null
收集变量-ErrorVariable err
中的任何错误以供以后检查:$err
用于消除错误;不支持通用的2>$null
参数(-ErrorAction
,-WarningAction
,-InformationAction
都不支持);请注意,如果-PipelineVariable
恰好生效,则2>$null
会触发脚本终止错误。无保证顺序
$ErrorActionPreference = 'Stop'
参数,将结果作业对象与-AsJob
一起使用以等待所有线程完成,此时可以调用Wait-Job
来按输入顺序接收所有输出。v6-中,最好使用Receive-Job
比Start-ThreadJob
,因为线程作业的开销要比基于后台进程的标准后台作业少得多。注意:PowerShell 6.x附带实现的Start-Job
模块;在Windows PowerShell中,您可以按需安装它;例如。:ThreadJob
。
Install-Module ThreadJob -Scope CurrentUser
注意,需要function PingRange ($from, $to) { $from..$to | ForEach-Object { Start-ThreadJob -ThrottleLimit ($to - $from + 1) { "192.168.0.$using:_`: $(Test-Connection -BufferSize 2 -TTL 5 -ComputerName 192.168.0.$using:_ -quiet -count 1)" } } | Receive-Job -Wait -AutoRemove -ErrorAction SilentlyContinue -ErrorVariable err | Sort-Object }
来引用封闭的$using:_
脚本块的ForEach-Object
变量。
虽然$_
使用
线程
(运行空间)运行其作业,但是可以使用标准作业cmdlet(即Start-ThreadJob
,Wait-Job
和Receive-Job
)管理所得的作业对象。Remove-Job
返回作业中命令的每个输出。这意味着,如果在作业内部抛出错误,则错误也会显示在Receive-Job
旁边。要解决此问题,请通过例如管道连接到receive-job
来紧密控制命令生成的输出。