Tags: PowerShell, Remote-Verwaltung
Befehle oder Scripts, deren Abarbeitung länger dauert, kann PowerShell in den Hintergrund schicken. Damit bleibt die Kommandozeile frei für weitere Eingaben und der Benutzer kann die Ergebnisse nach Abschluss des Jobs abrufen. Dies funktioniert auch mit der Ausführung von Befehlen auf Remote-PCs.
Grundsätzlich ist es keine neue Idee, Kommandos in einer interaktiven Shell im Hintergrund zu starten, so dass man in der Zwischenzeit weiterhin Zugriff auf den Prompt hat. Während dieses Konzept unter Unix schon lange realisiert wurde, kannte der alte Kommandointerpreter aber nichts Vergleichbares. PowerShell hingegen bietet ein umfangreiches Instrumentarium für das Job-Management.
Mehrere Varianten zum Starten von Jobs
Viele Cmdlet sehen den Start als Hintergrund-Job von Haus aus vor, indem sie den Parameter AsJob unterstützen. Sie benötigen somit kein externes Kommando, um diesen Modus zu aktivieren. Wenn man wissen möchte, welche Cmdlets diese Option vorsehen, dann kann man dies folgendermaßen herausfinden:
Get-Command -ParameterName AsJob
Unter Windows 10 mit installiertem Hyper-V-Modul gibt dieser Befehl über 200 Cmdlets aus.
Möchte man etwa eine oder mehrere VMs im Hintergrund starten, anstatt die Fortschrittsanzeige zu betrachten, dann könnte man dies so tun:
Start-VM -Name win10pro-vm2 -AsJob
Dieser Verfahren klappt genauso, wenn man eine interaktive Remote-Session mit Enter-PSSession aufgebaut hat. Der Unterschied besteht nur darin, dass die Befehle des Jobs auf dem Remote-Host laufen.
Eine weitere Variante, um Remote-Befehle im Hintergrund auszuführen, ergibt sich, wenn ein Cmdlet zusätzlich den Parameter ComputerName unterstützt:
Stop-VM -ComputerName win81-i7-L1 -Name WS2016-VM1 -AsJob
Start-Job
Möchte man ein Script im Hintergrund starten oder ein Cmdlet, das den Schalter AsJob nicht vorsieht, dann hilft hier Start-Job:
Start-Job -ScriptBlock {Get-Process -Name *Power*}
Die auszuführenden Befehle bzw. Scripts müssen dem Cmdlet in geschweiften Klammern übergeben werden, der Parametername ScriptBlock ist dabei optional. Diese Methode eignet sich, um einen Hintergrund-Job lokal zu starten oder in einer interaktiven Remote-Sitzung, die man mit Enter-PSSession geöffnet hat.
Will man jedoch einen Job remote starten, ohne explizit eine Session mit einem Host aufzubauen, dann erfüllt Invoke-Command im Zusammenspiel mit dem Schalter AsJob diese Aufgabe:
Invoke-Command -Computername WS2016-VM1 -ScriptBlock {Get-Process -Name *Power*} -AsJob
Das Ergebnis dieses Jobs gelangt schließlich zurück an den lokalen Rechner.
Status von Jobs überwachen
Unabhängig davon, wie man einen Befehl oder ein Script im Hintergrund startet, gibt PowerShell einige wesentliche Informationen des Jobs am Bildschirm aus. Dazu gehören vor allem die ID, der Status und Rechner, auf dem er läuft.
Alternativ kann man diese Daten in einer Variablen speichern, indem man diese die Referenz auf das Job-Objekt zuweist. In diesem Fall erscheinen die genannten Informationen nicht auf Stdout und das Management des Jobs erfolgt dann über die betreffende Variable:
$MyJob = Start-Job -ScriptBlock {Get-Process -Name *Power*}
Will man später Einblick in den Fortschritt eines Jobs gewinnen, dann dient Get-Job diesem Zweck. Ohne Parameter zeigt er sämtliche Jobs dieser Session an. Alternativ übergibt man dem Cmdlet entweder die ID oder den Namen eines oder mehrerer Jobs:
Get-Job -ID 29
Hat man die Referenz zum Job-Objekt in einer Variablen gespeichert, dann gibt man einfach ihren Inhalt aus.
Darüber hinaus kann man die Job-Liste anhand verschiedener Eigenschaften filtern. So erlauben die Parameter HasMoreData oder State die Ausgabe jener Jobs, von denen noch Ergebnisse abzuholen sind bzw. die einen bestimmten Status wie Completed oder Stopped aufweisen.
Ergebnisse von Hintergrund-Jobs abrufen
Die meisten Kommandos liefern ein Ergebnis, das man nach Beendigung des Jobs abholen möchte. Dieser Part kommt dem Cmdlet Receive-Job zu. In der einfachsten Form übergibt man ihm die ID oder den Namen den Jobs, alternativ über den Parameter Job die Referenz auf das Objekt, das man in einer Variablen gespeichert hat:
$job = Invoke-Command -Computername WS2016-VM1 -ScriptBlock {Get-Process} -AsJob
Receive-Job -Job $job
Mit diesem Kommando erhält man die Daten, die das Script bzw. die Befehle im ScriptBlock bis zu diesem Zeitpunkt generiert haben. Standardmäßig löscht Receive-Job diese an der Quelle, so dass man beim nachfolgenden Aufruf bloß die nächste Tranche der Daten erhält, die man dann Stück für Stück zusammenführen muss.
Wenn man das nicht möchte, dann sorgt der Schalter Keep dafür, dass bei jedem Abruf mittels Receive-Job sämtlicher bis dahin produzierter Output zurückgegeben wird:
Receive-Job -ID 19 -keep
Entsprechend bleibt die Eigenschaft HasMoreData des Jobs auf True.
Alternativ dazu kann man Receive-Job mit dem Schalter Wait dazu zwingen, solange zu warten, bis der Job vollständig abgearbeitet ist. In diesem Fall blockiert das Cmdlet jedoch den Prompt, was letztlich nicht im Sinne von Hintergrund-Jobs ist.
Jobs anhalten oder löschen
Wenn sich herausstellt, dass ein Script zu lange im Hintergrund läuft, weil es möglichweise wegen eines Programmierfehlers seinen Auftrag nie erfüllen wird, dann kann man es anhalten oder löschen.
Die erste Option kommt vor allen dann in Betracht, wenn man die bis zum jeweiligen Zeitpunkt erzeugten Daten noch mittels Receive-Job abholen möchte. In diesem Fall ruft man das Cmdlet Stop-Job auf, wobei man den Job wieder über die ID angeben kann.
Will man Jobs ganz entfernen, dann greift man dafür auf Remove-Job zurück. Auch dieses Cmdlet erwartet die Job-ID. Möchte man alle Jobs abräumen, die bereits gelaufen sind, dann könnte man das so machen:
Get-Job -State Completed | Remove-Job
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
- ThinPrint 13 unterstützt Microsofts V4-Druckertreiber und MMC
- PowerShell 7.3: JEA über SSH, Cmdlet für Setup, erweiterte ARM-Unterstützung
- Second-Hop-Problem: CredSSP für PowerShell-Remoting konfigurieren
- Drucker (remote) über PowerShell installieren
- PowerShell für Exchange auf Workstation installieren
Weitere Links
1 Kommentar
Guten Tag,
ist es auch möglich über die Job-ID an einen Fehlerlog zu kommen, falls der Job fehlgeschlagen ist?
Viele Grüße
Julias