3

为列表中的每个服务器运行一个作业。我只希望一次运行 5 个作业。当作业完成时,它应该在列表中的下一个服务器上启动一个新作业。到目前为止,这是我所拥有的,但在前 5 个工作运行之后,我无法让它开始新工作:

   $MaxJobs = 5
   $list = Get-Content ".\list.csv"
   $Queue = New-Object System.Collections.Queue
   $CurrentJobQueue = Get-Job -State Running
   $JobQueueCount = $CurrentJobQueue.count

   ForEach($Item in $list)
  {
  Write-Host "Adding $Item to queue"
  $Queue.Enqueue($Item)
  }

 Function Global:Remote-Install
 {
 $Server = $queue.Dequeue()
 $j = Start-Job -Name $Server -ScriptBlock{

        If($JobQueueCount -gt 0)
        {
        Test-Connection $Server -Count 15
        }##EndIf
    }##EndScriptBlock

  }

For($i = 0 ;$i -lt $MaxJobs; $i++) 
{
Remote-Install
}
4

2 回答 2

4

如果您使用,PowerShell 将为您执行此操作,Invoke-Command例如:

Invoke-Command -ComputerName $serverArray -ScriptBlock { .. script here ..} -ThrottleLimit 5 -AsJob

顺便说一句,我认为您对 .NET 队列的使用不会起作用,因为 Start-Job 会启动另一个 PowerShell 进程来执行该作业。

于 2013-01-05T17:57:10.380 回答
3

您可以查看Split-Pipeline模块SplitPipeline的 cmdlet 。代码将如下所示:

Import-Module SplitPipeline
$MaxJobs = 5
$list = Get-Content ".\list.csv"
$list | Split-Pipeline -Count $MaxJobs -Load 1,1 {process{
    # process an item from $list represented by $_
    ...
}}

-Count $MaxJobs限制并行作业的数量。-Load 1,1告诉将 1 个项目准确地输送到每个作业。

这种方法的优点是代码本身是同步调用的,并且它从作业中输出结果,就好像所有都是顺序调用的一样(甚至输出顺序也可以通过 switch 保留Order)。

但是这种方法不使用远程处理。该代码在多个运行空间中的当前 PowerShell 会话中工作。

于 2013-01-05T18:18:07.543 回答