12

ОбзораPowershell: Запуск нескольких рабочих мест в parralel и просматривать потоковые результаты фоновых заданий

Глядя вызвать скрипт Powershell, который принимает в качестве аргумента, проходит каждую работу в фоновом режиме, и показывает мне подробный вывод.

Проблема Я бегу в

Сценарий кажется бежать, но я хочу, чтобы проверить это наверняка потоковом результаты фоновых заданий, как они работают.

Код

###StartServerUpdates.ps1 Script### 

#get list of servers to update from text file and store in array 
$servers=get-content c:\serverstoupdate.txt 

#run all jobs, using multi-threading, in background 
ForEach($server in $servers){ 
    Start-Job -FilePath c:\cefcu_it\psscripts\PSPatch.ps1 -ArgumentList $server 
} 

#Wait for all jobs 
Get-Job | Wait-Job 

#Get all job results 
Get-Job | Receive-Job 

То, что я в настоящее время видим:

Id    Name   State  HasMoreData  Location    Command     
--    ----   -----  -----------  --------    -------     
23    Job23   Running True   localhost   #patch server ...   
25    Job25   Running True   localhost   #patch server ...   

То, что я хочу видеть:

Searching for approved updates ... 

Update Found: Security Update for Windows Server 2003 (KB2807986) 
Update Found: Windows Malicious Software Removal Tool - March 2013 (KB890830) 

Download complete. Installing updates ... 

The system must be rebooted to complete installation. 
cscript exited on "myServer" with error code 3. 
Reboot required... 
Waiting for server to reboot (35) 

Searching for approved updates ... 

There are no updates to install. 
cscript exited on "myServer" with error code 2. 
Servername "myServer" is fully patched after 2 loops 

Я хочу быть в состоянии увидеть выход или магазин, где-то, так что я могу сослаться назад, чтобы убедиться, что сценарий побежал и увидеть, какие серверы перезагружается и т.д.

Вывод:

В прошлом я запустил скрипт, и он прошел обновление серверов по одному и дал мне результат, который я хотел, но когда я начал делать больше серверов, эта задача заняла слишком много времени, поэтому я пытаюсь использовать фоновые задания с помощью «Start- Работа».

Может ли кто-нибудь помочь мне понять это, пожалуйста?

ответ

4

Вы можете ознакомиться с модулем SplitPipeline. Это специально для таких задач. Работает демо-код:

# import the module (not necessary in PS V3) 
Import-Module SplitPipeline 

# some servers (from 1 to 10 for the test) 
$servers = 1..10 

# process servers by parallel pipelines and output results immediately 
$servers | Split-Pipeline {process{"processing server $_"; sleep 1}} -Load 1, 1 

Для вашей задачи заменить "processing server $_"; sleep 1 (имитирует медленную работу) с вызовом вашего скрипта и использовать переменную $_ в качестве входных данных, текущий сервер.

Если каждое задание не является интенсивным процессором, то для повышения производительности увеличьте параметр Count (по умолчанию - количество процессоров).

+0

Роман, спасибо за ваш ответ. Это самое близкое, что я мог получить, имея результат точно так, как я этого хотел. Я получаю некоторые дополнительные ошибки вывода, которые я буду устранять, но этот метод не только запускает мой скрипт, но и показывает мне результат, который я хочу. Спасибо. –

+0

@ talbert.houle, я рад, что вы нашли этот инструмент полезным. Если у вас есть идеи о том, как сделать это лучше, вы можете отправить их на сайт проекта. –

1

В вашем цикле ForEach вы захотите захватить вывод, сгенерированный работами, уже запущенными.

Пример Не Испытано

$sb = { 
    "Starting Job on $($args[0])" 
    #Do something 
    "$($args[0]) => Do something completed successfully" 
    "$($args[0]) => Now for something completely different" 
    "Ending Job on $($args[0])" 
} 
Foreach($computer in $computers){ 
    Start-Job -ScriptBlock $sb -Args $computer | Out-Null 
    Get-Job | Receive-Job 
} 

Теперь, если вы делаете это все ваши результаты будут неоднозначными. Возможно, вы захотите поставить штамп на свой подробный вывод, чтобы сообщить, из какого вывода.

Или

Foreach($computer in $computers){ 
    Start-Job -ScriptBlock $sb -Args $computer | Out-Null 
    Get-Job | ? {$_.State -eq 'Complete' -and $_.HasMoreData} | % {Receive-Job $_} 
} 
while((Get-Job -State Running).count){ 
    Get-Job | ? {$_.State -eq 'Complete' -and $_.HasMoreData} | % {Receive-Job $_} 
    start-sleep -seconds 1 
} 

Он покажет все результаты, как только работа закончена. Не путайте.

+0

Благодарим вас за информацию. К сожалению, я попробовал первый блок кода, и все, что я получил на экране, было «Запуск задания на имя сервера». Подождали более 20 минут, чтобы обеспечить запуск сценария на удаленном сервере, и это все, что я получаю. Попробует второй блок кода и посмотрим, что-нибудь изменится. –

+0

[Вот ссылка] (http://www.powershellmagazine.com/2013/02/13/pstip-streaming-results-from-background-jobs-in-powershell-3-0/) к чему-то, что может быть больше полезно. –

1

Если вы хотите выполнить несколько заданий, вы, вероятно, захотите массировать выходные данные, чтобы помочь сохранить результат, с которым работает прямо на консоли.

$BGList = 'Black','Green','DarkBlue','DarkCyan','Red','DarkGreen' 
$JobHash = @{};$ColorHash = @{};$i=0 


ForEach($server in $servers) 
{ 
    Start-Job -FilePath c:\cefcu_it\psscripts\PSPatch.ps1 -ArgumentList $server | 
    foreach { 
      $ColorHash[$_.ID] = $BGList[$i++] 
      $JobHash[$_.ID] = $Server 
      } 
} 
    While ((Get-Job).State -match 'Running') 
    { 
    foreach ($Job in Get-Job | where {$_.HasMoreData}) 
     { 
     [System.Console]::BackgroundColor = $ColorHash[$Job.ID] 
     Write-Host $JobHash[$Job.ID] -ForegroundColor Black -BackgroundColor White 
     Receive-Job $Job 
     } 
    Start-Sleep -Seconds 5 
    } 
[System.Console]::BackgroundColor = 'Black' 
+0

Когда я просматриваю этот код, скрипт работает прямо над оператором «Пока», и я не получаю никакого вывода на консоль. –

+0

Единственное, что я знаю, это приведет к тому, что для $ servers будет пусто/null. Я тестировал с помощью этого scritpblock для действия задания: {foreach ($ i в 1..10) {get-date; sleep -Seconds 2}}, чтобы создать задание, которое выполняется в течение 20 секунд, и производит вывод каждые 2 секунды, и $ servers = (1..3) в качестве списка серверов. – mjolinor

3

не новый вопрос, но я чувствую, что отсутствует ответ в том числе Powershell с помощью рабочих процессов и ее параллельные возможности, от Powershell версии 3. Что меньше кода и может быть более понятным, чем начинать и ждать заданий, которые из Конечно, хорошо работает.

У меня есть два файла: TheScript.ps1 который координирует серверы и BackgroundJob.ps1 что-то вроде проверки. Они должны находиться в одном каталоге.

Write-Output в фоновом файле задания записывается в тот же поток, который вы видите при запуске TheScript.ps1.

TheScript.ps1:

workflow parallelCheckServer { 
    param ($Servers) 
    foreach -parallel($Server in $Servers) 
    { 
     Invoke-Expression -Command ".\BackgroundJob.ps1 -Server $Server" 
    } 
} 

parallelCheckServer -Servers @("host1.com", "host2.com", "host3.com") 

Write-Output "Done with all servers." 

BackgroundJob.ps1 (например):

param (
    [Parameter(Mandatory=$true)] [string] $server 
) 

Write-Host "[$server]`t Processing server $server" 
Start-Sleep -Seconds 5 

Так при запуске TheScript.ps1 он будет писать "сервер обработки" 3 раза, но это не будет ждать 15 секунд, но вместо этого 5, потому что они запускаются параллельно.

[host3.com] Processing server host3.com 
[host2.com] Processing server host2.com 
[host1.com] Processing server host1.com 
Done with all servers. 
+0

Мне нравится, что этому ответу не нужна сторонняя библиотека! –

0

Вы можете получить результаты, делая что-то вроде этого после того, как все рабочие места были получены:

$ массив = @() Get-Job -Name * | где {$ array + = $ _. ChildJobs.output}

.ChildJobs.output будет иметь все, что было возвращено в каждом задании.

 Смежные вопросы

  • Нет связанных вопросов^_^