Befehle parallel in PowerShell ausführen
- das Windows PowerShell-Multithreading
- Parallele Ausführung von Skripten mit PSJobs
- Behalten Sie unsere Jobs im Auge
- Auftragsausgabe abrufen
- Geplante Jobs erstellen
Die standardmäßige PowerShell-Sitzung ist Single-Threaded. Es führt einen Befehl aus und wechselt zum nächsten Befehl.
Diese Methode ist ausgezeichnet, da sie alles wiederholbar hält und nicht viele Ressourcen verbraucht. In diesem Fall ist es an der Zeit, über Multithreading nachzudenken.
In diesem Artikel lernen wir, verschiedene PowerShell-Multithreading-Techniken zu verstehen und zu verwenden, um mehrere Datenströme gleichzeitig zu verarbeiten, aber über dieselbe Konsole zu verwalten.
das Windows PowerShell-Multithreading
Multithreading ist eine Methode, um mehr als einen Befehl gleichzeitig auszuführen. PowerShell verwendet normalerweise einen einzelnen Thread; Es gibt viele Möglichkeiten, mehr als einen zu verwenden, um unser Skript zu parallelisieren.
Der Hauptzweck von Multithreading besteht darin, die Laufzeit des Codes zu verkürzen. Diese Zeitverringerung geht mit einer höheren Verarbeitungsleistungsanforderung einher.
Außerdem werden beim Multithreading viele Aktionen gleichzeitig ausgeführt, wodurch mehr Systemressourcen benötigt werden.
Beachten Sie, dass wir keine perfekte Skalierung sehen werden. Das Hoch- und Herunterfahren von Elementen im Skript wird einige Zeit in Anspruch nehmen.
PowerShell muss den Code mit einem einzigen Thread ausführen, und fertig. Wir verwenden den ursprünglichen Thread, der zum Ausführen unserer Konsole verwendet wurde, um die anderen Threads mit mehreren Threads zu verwalten.
Dieser ursprüngliche Thread wird an einem bestimmten Punkt ausgeschöpft, wodurch alle anderen Threads in einer Reihe bleiben.
Parallele Ausführung von Skripten mit PSJobs
Eine der bequemsten Möglichkeiten zum Multithreading eines Skripts ist mit PSJobs
. PSJobs
haben Cmdlets, die in das Modul Microsoft.PowerShell.Core
integriert sind.
Das Modul Microsoft.PowerShell.Core
ist seit Version 3 in allen Versionen von PowerShell enthalten. Befehle in diesem Modul ermöglichen es uns, Code im Hintergrund auszuführen, während anderer Code im Vordergrund weiter ausgeführt wird.
Get-Command *-Job
Behalten Sie unsere Jobs im Auge
Nachfolgend finden Sie eine Liste der häufigsten Zustände, die ein Job haben kann.
Abgeschlossen
– Der Auftrag ist abgeschlossen und wir können die Ausgabedaten abrufen oder den Auftrag entfernen.Running
– Der Job wird ausgeführt und kann nicht entfernt werden, ohne den Job zwangsweise zu stoppen. Ausgabe kann nicht abgerufen werden.Blockiert
– Der Job wird noch ausgeführt, aber der Benutzer wird zur Eingabe zusätzlicher Informationen aufgefordert, bevor er mit der Ausführung fortfahren kann.Fehlgeschlagen
– Während der Ausführung des Jobs ist ein ausgelöster Abbruchfehler aufgetreten.
Wir verwenden den Befehl Get-Job
, um den Status des gestarteten Jobs und alle Attribute unserer Jobs abzurufen. Die Ausgabe für einen Job, bei dem wir den Status sehen können, ist Running
.
Das folgende Beispiel führt den Code Start-Sleep 5
innerhalb eines Termins mit dem Befehl Start-Job
aus. Der Status dieses Jobs wird dann mit dem Befehl Get-Job
zurückgegeben.
Beispielcode:
Start-Job -Scriptblock {Start-Sleep 5}
Get-Job
Ausgang:
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
1 Job1 BackgroundJob Running True localhost Start-Sleep 5
Auftragsausgabe abrufen
Manchmal gibt der Code innerhalb des Jobs die Ausgabe zurück. Wir können diesen Code mit dem Befehl Receive-Job
abrufen.
Es akzeptiert PSJob
als Eingabe und schreibt dann die Arbeit des Jobs auf die Konsole. Alles, was sich während der Ausführung des Jobs ergeben hat, wurde gespeichert.
Wenn der Job abgerufen wird, zeigt er alles, was gespeichert wurde.
Ein Beispiel hierfür wäre die Ausführung des folgenden Skripts. Dieses Skript erstellt und startet einen Job, um die Zeichenfolge Hello World
in die Ausgabe zu schreiben.
Anschließend ruft es die Ausgabe des Jobs ab und zeigt sie auf der Konsole an.
Beispielcode:
$Job = Start-Job -ScriptBlock {Write-Output 'Hello World'}
Receive-Job $Job
Ausgang:
Hello World
Geplante Jobs erstellen
Eine andere Möglichkeit, mit PSJobs
zu interagieren, ist über einen geplanten Job. Es ähnelt einer geplanten Windows-Aufgabe, die wir mit dem Taskplaner konfigurieren können.
Geplante Termine schaffen eine Möglichkeit, komplexe PowerShell-Skriptblöcke einfach in einer geplanten Aufgabe zu planen. Dann können wir basierend auf Triggern einen PSJob
im Hintergrund ausführen.
Job-Trigger
Auftragsauslöser können ein bestimmter Zeitpunkt sein, zu dem sich ein Benutzer anmeldet, wenn das System hochfährt, und viele andere. Wir können die Trigger auch in Intervallen wiederholen lassen.
Diese Trigger werden mit dem Befehl New-JobTrigger
definiert, der einen Trigger angibt, der den geplanten Job ausführt.
Zusätzlich zu einem PSJob-Trigger hätten wir immer noch einen Skriptblock, wie er bei einem normalen PSJob
verwendet wird. Sobald wir sowohl den Auslöser als auch den Skriptblock haben, würden wir den Befehl Register-ScheduledJob
verwenden, um den Job zu erstellen, wie im nächsten Abschnitt gezeigt.
Dieser Befehl gibt Attribute des geplanten Jobs an, wie den Skriptblock, der ausgeführt wird, und Trigger, die mit dem Befehl New-JobTrigger
erstellt werden.
Vielleicht brauchen wir PowerShell-Code, der jedes Mal ausgeführt wird, wenn sich jemand an einem Computer anmeldet. Wir können dafür einen geplanten Job erstellen.
Wir würden zuerst einen Trigger mit New-JobTrigger
definieren und den geplanten Job wie unten angegeben spezifizieren. Dieser geplante Job unten schreibt jedes Mal, wenn sich jemand beim System anmeldet, eine Zeile in eine Protokolldatei.
Beispielcode:
$Trigger = New-JobTrigger -AtLogon
$Script = {"User $env:USERNAME logged at $(Get-Date -Format 'y-M-d H:mm:ss')" | Out-File -FilePath C:\Temp\User_Login.log -Append}
Register-ScheduledJob -Name Login_Log -ScriptBlock $Script -Trigger $Trigger
Ausgang:
Id Name JobTriggers Command Enabled
-- ---- ----------- ------- -------
1 Login_Log 1 "User $env:USERNAME logged at $(Ge... True
Sobald wir die obigen Befehle ausführen, erhalten wir ein ähnliches Ergebnis wie bei einem neuen Job, der die ID, den Skriptblock und einige andere Attribute anzeigt.
Verwenden Sie den AsJob
-Parameter
Eine weitere Verwendung von Jobs ist der Parameter -AsJob
, der in viele PowerShell-Befehle integriert ist. Da es viele verschiedene Befehle gibt, können wir sie alle mit Get-Command
finden.
Get-Command -ParameterName AsJob
Eines der am weitesten verbreiteten Cmdlets ist Invoke-Command
. Wenn wir diesen Befehl ausführen, beginnt er normalerweise sofort mit der Ausführung eines Befehls.
Während einige Befehle jedoch sofort zurückgegeben werden, sodass wir mit dem fortfahren können, was wir gerade getan haben, warten einige, bis das Cmdlet abgeschlossen ist.
Während wir den Parameter AsJob
die meiste Zeit mit dem lokalen Computer verwenden können, hat das Cmdlet Invoke-Command
keine native Option, um auf dem lokalen Computer ausgeführt zu werden. Es gibt jedoch eine Problemumgehung, indem Sie Localhost
als Parameterwert ComputerName
verwenden.
Beispiel:
Invoke-Command -ScriptBlock {Start-Sleep 5} -ComputerName localhost
Das folgende Skript verwendet das Invoke-Command
-Cmdlet, um fünf Sekunden lang zu schlafen, und wiederholt dann denselben Befehl mit dem AsJob
-Parameter, um den Unterschied in den Ausführungszeiten anzuzeigen.
Beispielcode:
Measure-Command {Invoke-Command -ScriptBlock {Start-Sleep 5}}
Measure-Command {Invoke-Command -ScriptBlock {Start-Sleep 5} -AsJob -ComputerName localhost}
Ausgang:
Days : 0
Hours : 0
Minutes : 0
Seconds : 5
Milliseconds : 20
Ticks : 50206571
TotalDays : 5.81094571759259E-05
TotalHours : 0.00139462697222222
TotalMinutes : 0.0836776183333333
TotalSeconds : 5.0206571
TotalMilliseconds : 5020.6571
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 36
Ticks : 365754
TotalDays : 4.23326388888889E-07
TotalHours : 1.01598333333333E-05
TotalMinutes : 0.00060959
TotalSeconds : 0.0365754
TotalMilliseconds : 36.5754
Marion specializes in anything Microsoft-related and always tries to work and apply code in an IT infrastructure.
LinkedIn