1

我试图更好地了解 powershell 如何处理作业。

这两篇文章都有很大帮助:

但是,使用以下示例脚本,我在调用 Receive-Job 时得到了意想不到的结果。我希望每一行都有一个结果,但有时我会看到每行有多个结果或额外的空白回车。关于如何只写出每个作业从控制台流入的信息的任何想法?

$loops = 1..10
$jobs = new-object System.Collections.ArrayList

$loops | % {
    $jobs.add( 
        (start-job -ScriptBlock {
            param($list)
            $list | % {
                sleep -seconds (get-random -Maximum 3 -Minimum 1)
                write-host "Number is: $_"
            }
        } -ArgumentList (,$loops))
    ) | out-null
}


while ($jobs.count -gt 0)
{
    if ($jobs -ne $null)
    {
        $list = $jobs | ? { $_.HasMoreData -eq $true }
        $list | % { Receive-Job -Job $_ }
        $list2 = $jobs.Clone() | ? { $_.State -eq "Completed" }
        $list2 | % {
            $jobs.Remove($_) | out-null
        }
        $list = $null
    }
}

输出可以...

数量是:1
数量是:1
数量是:2

或者有时...

数量是:1
数量是:2
号码是:1号码是:2
号码是:1号码是:2号码是:2
4

1 回答 1

3

你把这件事复杂化了很多。您不需要所有这些循环来手动处理事情。您应该利用可用的 cmdlet。这应该实现您想要的基础知识:

$loops = 1..10

$scriptBlock = {
  param($list)
  $list | % {
    sleep -seconds (get-random -Maximum 3 -Minimum 1)
    write-host "Number is: $_"
  }
}

$jobs = $loops | % { start-job -ScriptBlock $scriptBlock -ArgumentList (,$loops) }

$jobs | Wait-Job | Receive-Job

但是,这会将所有输出组合在一起,但无法知道什么工作做了什么。而且您正在使用的事实Write-Host意味着您实际上无法访问数据,它只是打印到屏幕上。

如果您想实际存储或处理生成的作业输出,可以执行以下操作:

$loops = 1..10

$scriptBlock = {
  param($list)
  $list | % {
    sleep -seconds (get-random -Maximum 3 -Minimum 1)
    "Number is: $_"  # don't use write-host, just output the string
  }
}

$jobs = $loops | % { start-job -ScriptBlock $scriptBlock -ArgumentList (,$loops) }

$jobs | Wait-Job  # wait for all jobs to be complete
$jobs |%{
   $output = $_ | Receive-Job
   # process $output here, do what you want with it
}
于 2012-08-23T03:37:11.707 回答