Очередь заданий PowerShell

Запустите задание для каждого сервера в списке. Я хочу только 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
}

person Joe Brown    schedule 05.01.2013    source источник
comment
Это то, что я в итоге сделал... Думаю, это сработает для меня. $list = Get-Content .\list.csv $queue = [System.Collections.Queue]::Synchronized((New- Object System.Collections.Queue)) ForEach($Item in $list) { Write-Host Добавление $Item в очередь $Queue.Enqueue($Item) } $Server = $queue.Dequeue() foreach ($server в $list ){ $running = Get-Job | Where-Object { $_.JobStateInfo.State -eq 'Выполняется' } if ($running.Count -le 2) { .. Сценарий здесь .. } else { $running | Ожидание задания } }   -  person Joe Brown    schedule 05.01.2013


Ответы (2)


PowerShell сделает это за вас, если вы используете Invoke-Command, например:

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

Кстати, я не думаю, что ваше использование .NET Queue будет работать, потому что Start-Job запускает другой процесс PowerShell для выполнения задания.

person Keith Hill    schedule 05.01.2013
comment
Спасибо за информацию. Особенность Invoke-Command в том, что он хочет, чтобы вы вызывали команду на другом компьютере. - person Joe Brown; 05.01.2013

Вы можете взглянуть на командлет Split-Pipeline модуля SplitPipeline. Код будет выглядеть так:

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 элемент на каждое задание.

Преимущество такого подхода в том, что сам код вызывается синхронно и выводит результаты заданий, как если бы все вызывалось последовательно (даже порядок вывода можно сохранить с помощью переключателя Order).

Но этот подход не использует удаленное взаимодействие. Код работает в текущем сеансе PowerShell в нескольких пространствах выполнения.

person Roman Kuzmin    schedule 05.01.2013