PowerShell通过作业快速Ping子网 [英] PowerShell quickly Ping Subnet with Jobs

查看:102
本文介绍了PowerShell通过作业快速Ping子网的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下功能将使用PingRange 1 254 ping我的子网以检查IP:

The following function will ping my subnet with PingRange 1 254 to check IP's:

function PingRange ($from, $to) {
    $from..$to | % {"192.168.0.$($_): $(Test-Connection -BufferSize 2 -TTL 5 -ComputerName 192.168.0.$($_ ) -quiet -count 1)"}
}

但是,这很慢,所以我想知道是否可以同时对它们全部执行ping操作,然后收集结果.我想这将意味着:

However, this is slow, so I was wondering if it's possible to ping them all concurrently, then collect the results. I guess that this would mean:

  1. 在每个Test-Connection上使用Start-Job(我可以做到,这一部分很简单).

  1. Using Start-Job on each Test-Connection (which I can do, that part is easy).

等待所有完成.

仅收集ping成功结果并将其排序.

Collecting only the ping success results and sorting them.

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 }

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 }

是否有一种简便的方法来进行等待作业,该等待作业将等待所有 产生的作业完成?

Is there a shorthand way to do a Wait-Job that will just wait for all spawned jobs to complete?

接收信息似乎也很棘手,当我尝试接收信息时,我总是从Receive-Job那里得到任何东西(通常是一个讨厌的错误).希望有更多关于PowerShell Jobs的专家知道如何轻松获得这些结果?

Receiving the information also seems tricky, and when I try it, I invariable get nothing back from Receive-Job (or a nasty error usually). Hopefully someone more expert on PowerShell Jobs knows how to grab these results easily?

推荐答案

注意:在 Windows PowerShell 中,最简单的解决方案是使用Test-Connection -AsJob,如js2010的答案.但是,PowerShell [Core] 6+不再支持-AsJob.
该答案集中在与命令无关的方法上,以实现与作业的并发.

Note: In Windows PowerShell the simplest solution is to use Test-Connection -AsJob, as shown in js2010's answer. -AsJob is no longer supported in PowerShell [Core] 6+, however.
This answer focuses on command-agnostic ways to achieve concurrency with jobs.

在PowerShell v7 + 中,您将能够使用

In PowerShell v7+, you'll be able to use ForEach-Object -Parallel, which can greatly simplify your function, by running your commands in parallel, using different threads:

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个命令,其余的排队直到池中的一个线程再次可用,如先前的命令结束.

    • -ThrottleLimit defaults to 5, which means that up to 5 commands run in parallel, which additional ones queued until one threads in the pool become available again, as previous commands finish.

      • Here, I've chosen to allow all threads to run in parallel, but you'll have to test if that works in practice - it may work for network-bound tasks such as here, but it's not right choice for CPU-bound tasks; see this blog post for guidance.

      2>$null使错误输出静音,但-ErrorVariable err收集变量$err中的所有错误以供以后检查:

      2>$null silences error output, but -ErrorVariable err collects any errors in variable $err for later inspection:

      • 注意:从v7.0开始,只有2>$null可以解决沉默错误;不支持通用的-ErrorAction参数(-WarningAction-InformationAction-PipelineVariable都不支持);请注意,如果$ErrorActionPreference = 'Stop'恰好生效,则2>$null可以触发脚本终止错误.
      • Note: As of v7.0, only 2>$null works for silencing errors; the common -ErrorAction parameter is not supported (and neither are -WarningAction, -InformationAction, -PipelineVariable); note that 2>$null can trigger a script-terminating error if $ErrorActionPreference = 'Stop' happens to be in effect.

      线程的输出将以没有保证的顺序到达,但是将在到达时进行打印.

      Output from the threads will arrive in no guaranteed order, but will print as it arrives.

      • 考虑到您想要的排序输出,在这里这不是问题.
      • 如果确实需要按输入顺序的输出,请使用-AsJob参数,将生成的作业对象与Wait-Job一起使用,以等待所有线程完成,此时可以调用Receive-Job以输入顺序接收所有输出.
      • Given that your want sorted output anyway, that is not a problem here.
      • If you do need the output in input order, use the -AsJob parameter, use the resulting job object with Wait-Job to wait for all threads to finish, at which point you can call Receive-Job to receive all the outputs in input order.

      在PowerShell v6-中,使用Start-ThreadJobStart-Job 更好.因为线程作业的开销要比标准后台作业(子进程)少得多. -基于过程.

      In PowerShell v6-, it's better to use Start-ThreadJob than Start-Job, because thread jobs have much less overheads than the standard background jobs, which are child-process-based.

      注意:PowerShell 6.x附带实现的ThreadJob模块;在Windows PowerShell中,您可以按需安装它;例如.: Install-Module ThreadJob -Scope CurrentUser.

      Note: The implementing ThreadJob module ships with PowerShell 6.x; in Windows PowerShell you can install it on demand; e.g.: 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脚本块的$_变量.

      Note the need for $using:_ in order to reference the enclosing ForEach-Object script block's $_ variable.

      虽然Start-ThreadJob使用线程(运行空间)运行其作业,但是可以使用标准作业cmdlet(即Wait-JobReceive-JobRemove-Job)管理生成的作业对象.

      While Start-ThreadJob uses threads (runspaces) to run its jobs, the resulting job objects can be managed with the standard job cmdlets, namely Wait-Job, Receive-Job and Remove-Job.

      • Start-ThreadJob使用线程(通过PowerShell SDK分离进程内PowerShell runspaces )进行并发,而不是使用子进程 Start-Job使用.基于线程的并发速度更快,资源占用更少.

      • Start-ThreadJob uses threads (separate in-process PowerShell runspaces via the PowerShell SDK) for concurrency rather than the child processes Start-Job uses. Thread-based concurrency is much faster and less resource-intensive.

      • 有关Start-ThreadJob带来的性能提升的示例,请参见此答案.
      • See this answer for an example of the performance gains that Start-ThreadJob brings.

      线程作业的输出保留其原始类型.

      • 相反,在Start-Job作业中,输入和输出必须跨越进程边界,这需要在PowerShell remoting 中使用相同类型的基于XML的序列化和反序列化,其中丢失了类型保真度,除了一些已知类型以外:请参见此答案.
      • By contrast, in Start-Job jobs input and output must cross process boundaries, necessitating the same kind of XML-based serialization and deserialization that is used in PowerShell remoting, where type fidelity is lost except for a few known types: see this answer.

      Start-ThreadJob唯一的-很大程度上是假想的-崩溃的线程可能会使整个过程崩溃,但请注意,即使使用Throw创建的脚本终止错误也只会终止手头的线程(运行空间),而不是来电者.

      The only - largely hypothetical - downside of Start-ThreadJob is that a crashing thread could crash the entire process, but note even a script-terminating error created with Throw only terminates the thread (runspace) at hand, not the caller.

      简而言之:仅当需要完全隔离进程时使用Start-Job ;也就是说, if 您需要确保以下内容:

      In short: use Start-Job only if you need full process isolation; that is, if you need to ensure the following:

      • 崩溃的作业不能使调用者崩溃.

      • A crashing job must not crash the caller.

      作业不应看到将.NET类型加载到调用者的会话中.

      A job should not see .NET types loaded into the caller's session.

      作业不应能够修改调用方的环境变量(在两种类型的作业中,调用方的环境变量值均存在 ,但在这种情况下它们是的后台作业.)

      A job should not be able to modify the caller's environment variables (in jobs of both types the caller's environment variable values are present, but in the case of background jobs they are copies).

      请注意,在 Start-ThreadJobStart-Job作业中,这些作业 not 均以以下方式查看呼叫者的状态::

      Note that in both Start-ThreadJob and Start-Job jobs, the jobs do not see the caller's state in terms of:

        通过交互方式或通过$PROFILE文件将
      • 变量,函数,别名或PSv5 + 自定义类添加到调用者的会话中-作业不会加载$PROFILE文件.

      • Variables, functions, aliases, or PSv5+ custom classes added to the caller's session, either interactively or via a $PROFILE file - jobs do not load $PROFILE files.

      • 但是,线程作业确实会看到 .NET 类(类型)已加载到调用者的会话中,并且与常规作业不同,它们不仅可以看到调用者的环境变量的值,而且还可以修改它们.
      • However, thread jobs do see .NET classes (types) loaded into the caller's session, and, unlike regular jobs, they not only see the values of the caller's environment variables, but can also modify them.

      在PowerShell 6-中,作业的初始当前目录(文件系统位置)与调用方的不同.幸运的是,此问题已在v7 +中修复;一旦启动,作业将保持其自己的当前位置,并且对其进行更改不会影响调用者.

      In PowerShell 6-, the initial current directory (filesystem location) for jobs was not the same as the caller's; fortunately, this is fixed in v7+; once started, jobs maintain their own current location and changing it does not affect the caller.

      这篇关于PowerShell通过作业快速Ping子网的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆