2012-08-23 77 views
1

我试图更好地理解PowerShell如何处理作业。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 
    } 
} 

输出可...

 
Number is: 1 
Number is: 1 
Number is: 2 

或者有时候...

 
Number is: 1 
Number is: 2 
Number is: 1Number is: 2 
Number is: 1Number is: 2Number is: 2 

回答

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 
} 
+0

的感谢!你说得对,因为我过度复杂了剧本。我倾向于在实验中这样做。你的例子是完美的,除非我想在作业运行时获取数据,而不是等待工作?例如,我试图在作业运行时(通过写主机)将作业传送到主PowerShell控制台(这是脚本底部的所有循环的重点)。我是否正在走这条“这不是一份工作的目的/功能”的道路?在调用'Receive-Job'之前是否应该完成所有的工作? –

+1

这并不是说这不是工作的“目的”,只是这不是他们最擅长的,而且这不是您拥有的cmdlet支持。你可以做各种疯狂的循环和完成检查,并得到一些“流式”行为的表象,但它会非常复杂和容易出错。这是您的成本/收益决定。最好的工作是“我会去做这项工作,并在完成后处理结果。”如果你想要流式传输,你可以让每个作业写入不同的日志文件,并开始一个“尾部”进程来传输每个日志。 – latkin

+0

谢谢你,你一直很有帮助。在处理一些使用作业的示例项目时,我会记住您的建议。 –