Befehle parallel in PowerShell ausführen

  1. das Windows PowerShell-Multithreading
  2. Parallele Ausführung von Skripten mit PSJobs
  3. Behalten Sie unsere Jobs im Auge
  4. Auftragsausgabe abrufen
  5. Geplante Jobs erstellen
Befehle parallel in PowerShell ausführen

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.

  1. Abgeschlossen – Der Auftrag ist abgeschlossen und wir können die Ausgabedaten abrufen oder den Auftrag entfernen.
  2. Running – Der Job wird ausgeführt und kann nicht entfernt werden, ohne den Job zwangsweise zu stoppen. Ausgabe kann nicht abgerufen werden.
  3. 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.
  4. 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 Paul Kenneth Mendoza avatar Marion Paul Kenneth Mendoza avatar

Marion specializes in anything Microsoft-related and always tries to work and apply code in an IT infrastructure.

LinkedIn