12

PrzeglądPowerShell: uruchamianie wielu miejsc pracy w parralel i widok streamingu wyników z pracy tła

Patrząc zadzwonić skryptu PowerShell, które odbywają się w kłótnię, uruchamia każdą pracę w tle, i pokazuje mi wyjście opisowy.

Problem używam do

Skrypt wydaje się uruchomić, ale chcę, aby zweryfikować to na pewno przez strumieniowe wyniki pracy w tle, ponieważ są one uruchomione.

Kod

###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 

Co Ja obecnie zobaczyć:

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

Co chcę zobaczyć:

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 

Chcę móc zobaczyć wyjście lub sklepu, że gdzieś tak mogę odesłać do upewnij się, że skrypt i pobiegł zobaczyć, które serwery restartem itp

Wniosek:

W przeszłości, uruchomiłem skrypt i zaktualizowałem serwery po jednym na raz i otrzymałem żądany wynik, ale kiedy zacząłem robić więcej serwerów - zadanie to trwało zbyt długo, dlatego próbuję użyć tła pracy z "Start- Praca".

Czy ktoś może mi pomóc rozwiązać ten problem?

Odpowiedz

4

Możesz rzucić okiem na moduł SplitPipeline. Jest specjalnie zaprojektowany do takich zadań. Roboczy kod demo:

# 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 

Dla zadania zastąpić "processing server $_"; sleep 1 (symuluje powolną pracę) z wezwaniem do skryptu i użyć zmiennej $_ jako wejście bieżącego serwera.

Jeśli każde zadanie nie wymaga dużej mocy obliczeniowej, zwiększ parametr Count (domyślnie liczba procesorów) w celu zwiększenia wydajności.

+0

Roman, dziękuję za odpowiedź. To jest najbliżej, jak mogłem uzyskać wydruk dokładnie tak, jak tego chciałem. Dostaję dodatkowe błędy wyjściowe, które rozwiążę, ale ta metoda nie tylko uruchamia mój skrypt, ale pokazuje mi pożądany wynik. Dziękuję Ci. –

+0

@ talbert.houle, cieszę się, że narzędzie to jest przydatne. Jeśli masz pomysły na to, jak je ulepszyć, możesz je przesłać na stronie projektu. –

1

W swojej pętli ForEach będziesz chciał pobrać dane wyjściowe wygenerowane przez zadania już działające.

przykład nie Testowany

$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 
} 

Teraz, jeśli to wszystko Twoje wyniki będą mieszane. Możesz chcieć umieścić znaczek na swoim szczegółowym wyjściu, aby określić, z którego wyjścia pochodzi.

Albo

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 
} 

To pokaże wszystkie wyjścia, jak tylko praca jest zakończona. Bez pomieszania.

+0

Dziękujemy za informacje. Niestety, wypróbowałem pierwszy blok kodu, a wszystko, co otrzymałem na ekranie, to "Rozpoczęcie pracy na serwerze". Czekałem ponad 20 minut, aby skrypt działał na serwerze zdalnym, a to wszystko, co otrzymuję. Spróbuję użyć drugiego bloku kodu i zobaczę, czy coś się zmieni. –

+0

[Oto link] (http://www.powershellmagazine.com/2013/02/13/pstip-streaming-results-from-background-jobs-in-powershell-3-0/) na coś, co może być bardziej pomocny. –

1

Jeśli chcesz wykonywać wiele zadań, prawdopodobnie będziesz chciał masować wydruki, aby uzyskać informacje o tym, co daje wynik, a jakie zadanie można wykonać bezpośrednio na konsoli.

$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

Gdy przejdę przez ten kod, skrypt działa bezpośrednio nad instrukcją "While" i nie otrzymuję żadnych danych wyjściowych do konsoli. –

+0

Jedyne, co wiem, może spowodować, że $ serwery będą puste/zerowe. Przetestowałem przy użyciu tego narzędzia scritpblock dla działania zadania: {foreach ($ i in 1..10) {get-date; sleep -Seconds 2}}, aby utworzyć zadanie działające przez 20 sekund i generować wynik co 2 sekundy, oraz $ servers = (1..3) jako lista serwerów. – mjolinor

3

Nie nowe pytanie, ale czuję, że brakuje odpowiedzi w tym PowerShell za pomocą równoległych przepływów pracy i jego możliwości, z PowerShell w wersji 3. co jest mniej kodu, a może bardziej zrozumiałe niż uruchamianie i czekają na pracę, która z Oczywiście działa również dobrze.

Mam dwa pliki: TheScript.ps1, który koordynuje serwery i BackgroundJob.ps1, który wykonuje jakąś kontrolę. Muszą znajdować się w tym samym katalogu.

Write-Output w pliku zadania w tle zapisuje do tego samego strumienia, co podczas uruchamiania 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 (na przykład):

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

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

Więc podczas uruchamiania TheScript.ps1 będzie napisać "serwer przetwarzanie" 3 razy, ale nie będzie czekać na 15 sekund, ale zamiast tego 5, ponieważ działają równolegle.

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

Podoba mi się, że ta odpowiedź nie wymaga biblioteki innej firmy! –

0

można uzyskać wyniki robiąc coś takiego po wszystkich zadań zostały otrzymane:

$ array = @() Get-Job -Name * | gdzie {$ array + = $ _. ChildJobs.output}

. ChildJobs.output będzie mieć wszystko, co zostało zwrócone w każdym zadaniu.

Powiązane problemy