5 min read
Steigere deine IT Automations-Effizienz mit neuer ScriptRunner Version
Wir haben unser neuestes ScriptRunner-Update, Version 7.1, veröffentlicht. Dieses Update ist vollgepackt mit...
ScriptRunner Blog
Wie sicher bist du im Umgang mit der Pipeline? Wir starten eine neue, kleine Reihe – los geht es mit dem Thema PowerShell Pipeline Grundlagen. So erleichterst du dir als Administrator den Alltag.
Für zahlreiche Administratoren erscheint die Pipeline-Funktionalität in PowerShell als ein kaum zu entschlüsselndes Mysterium, das sie trotz seines enormen Potenzials oft umgehen. Auch, wenn zumindest die Grundlagen bekannt sind, ziehen es viele vor, sie nicht eigenständig zu nutzen und verlassen sich stattdessen hauptsächlich auf kopierten Code. Tatsächlich ist die Anwendung in der Praxis weniger komplex, als mancher annimmt, und wird nach einer kurzen Einarbeitungszeit fast intuitiv.
Das Pipelining ermöglicht eine nahtlose Verkettung mehrere Cmdlets, wodurch auch komplexe Aufgaben vereinfacht dargestellt werden können. Dieser Artikel beantwortet folgende Fragen:
Die Pipeline ermöglicht es zwei oder mehrere Cmdlets zu verketten. Die Ergebnisse eines Befehls werden an den nächsten Befehl weitergegeben. Als Verknüpfung der Befehle wird der senkrechte Strich (" | ") verwendet. Manch einer kennt dieses Vorgehen auch von der Linux-Bash. Die PowerShell hebt sich dabei insofern von der Bash-Pipe ab, als dass in der PowerShell komplette Objekte übergeben werden können statt reiner "dummer" Text.
Stell dir die PowerShell-Pipeline wie ein Fließband in einer Fabrik vor. Jedes Cmdlet ist wie eine Station auf diesem Fließband. Du setzt ein Produkt (z.B. ein Datenobjekt) am Anfang des Fließbands ab und es bewegt sich von Station zu Station. An jeder Station (Cmdlet) wird eine spezielle Handlung oder Bearbeitung an diesem Produkt vorgenommen, bevor es zur nächsten weitergeleitet wird. Wenn es das Ende des Fließbands erreicht, hast du ein fertiges Produkt, das alle erforderlichen Bearbeitungsschritte durchlaufen hat. Genau wie in einer Fabrik kannst du je nach Bedarf beliebig viele Stationen (Cmdlets) in der gewünschten Reihenfolge hinzufügen, um das perfekte Ergebnis zu erhalten.
Das folgende Code-Beispiel illustriert die Anwendung der PowerShell-Pipeline:
Get-Service -Name 'wuauserv' | Stop-Service
Zunächst wird ein Service-Objekt mit dem Namen "wuauserv" abgefragt. Das Ergebnis dieser Abfrage (= das Service-Objekt) wird nun mittels Pipeline an das nächste Cmdlet weitergereicht. Stop-Service bewirkt nun ein Stoppen sämtlicher Service-Objekte, über die Pipe weitergereicht wurden (in diesem Fall das "wuauserv"-Service-Objekt).
Deutlich spannender ist die Verknüpfung mehrerer Cmdlets. So könnte man über einen Filter zunächst gezielt nach bestimmten Services suchen und diese anschließend beenden. Angenommen es sollen sämtliche Services einer bestimmten Anwendung (in diesem Fall "Xbox") beendet werden, so könnte man folgende Verkettung benutzen:
Get-Service | Where-Object Displayname -like "*xbox*" | Stop-Service
Wie schon im letzten Code-Beispiel gezeigt, ist es möglich die Pipeline für das Filtern, Sortieren und Weiterleiten von Daten einzusetzen. Die wichtigsten Cmdlets hierfür sind:
Das Cmdlet Where-Object ist wie ein Sieb, das nur die gewünschten Objekte durchlässt. Möchtest du beispielsweise alle Dienste auf deinem System auflisten, aber nur diejenigen sehen, die momentan gestartet sind, so kannst du folgenden Code verwenden:
Get-Service | Where-Object { $_.Status -eq 'Running' }
Natürlich können mittels Where-Object auch komplexere Abfragen durchgeführt werden, wie in diesem Beispiel:
Get-ChildItem -Path 'C:\Logs' -File | Where-Object { $_.Extension -eq '.log' -and $_.Length -gt 1GB }
In diesem Fall werden alle Dateien im Ordner "C:\Logs" ausgegeben welche beide der folgenden Bedingungen erfüllen:
Das Cmdlet Sort-Object sorgt für eine entsprechende Sortierung der Daten. So kann man die Ausgabe eines Objekts anhand eines ausgewählten Attributs sortieren - folgendem Beispiel filtern wir sämtliche Services anhand des jeweiligen Status und sortieren anschließend anhand des Prozessnamens. Mit den Parametern -Ascending (aufsteigend) und -Descending (absteigend) lässt sich dabei die Reihenfolge festlegen:
Get-Service | Where-Object { $_.Status -eq 'Running' } | Sort-Object Name -Ascending
Get-Service | Where-Object { $_.Status -eq 'Running' } | Sort-Object Name -Descending
Das Cmdlet Select-Object ist ein nützliches Werkzeug, wenn man spezifische Eigenschaften aus den Objekten, die durch die Pipeline fließen, extrahieren möchte. Es ist besonders hilfreich, wenn man nur bestimmte Daten anzeigen oder weiterverarbeiten möchte. Hier ist ein einfacher Gebrauch von Select-Object, um nur die Namen und Status der auf einem System laufenden Dienste zu erhalten:
Get-Service | Select-Object Name, Status
Das Cmdlet Group-Object erlaubt es, Objekte nach einer oder mehreren Eigenschaften zu gruppieren. Dies ist besonders nützlich, wenn man eine große Menge an Daten hat und diese in logische Gruppen unterteilen möchte. Hier ein Beispiel, wo Group-Object verwendet wird, um Dienste nach ihrem Status zu gruppieren:
# Befehl:
Get-Service | Group-Object -Property Status
# Ausgabe:
In diesem Code-Block werden die Dienste nach ihrem Status gruppiert, und man erhält eine Ausgabe, die zeigt, wie viele Dienste in jedem Status (Laufend, Gestoppt, etc.) vorhanden sind.
Das Cmdlet Tee-Object ist nützlich, wenn man die Pipeline-Daten sowohl auf dem Bildschirm anzeigen als auch in eine Datei schreiben möchte. Es leitet die Daten an zwei Orte weiter – daher der Name "Tee" (wie eine T-Abzweigung). Hier ist ein Beispiel:
Get-Process | Tee-Object -FilePath "C:\temp\processlist.txt"
In dem oben genannten Code-Block werden die Prozessinformationen sowohl auf dem Bildschirm angezeigt als auch in die angegebene Datei geschrieben.
Das Cmdlet Foreach-Object ermöglicht es, eine Aktion oder eine Gruppe von Aktionen für jedes Objekt in der Pipeline durchzuführen. Dies ist besonders nützlich, wenn man eine spezifische Aufgabe für jedes Objekt in einer Liste ausführen möchte. Hier ist ein Beispiel:
Get-Service | Foreach-Object { if ($_.Status -eq 'Running') { Write-Output "$($_.Name) is running and its start type is $($_.StartType)" } }
In diesem Beispiel wird Foreach-Object verwendet, um durch alle Dienste zu iterieren. Wenn der Status eines Dienstes "Running" ist, wird eine Ausgabe erzeugt, die den Namen des Dienstes und seine Startart angibt.
Nachdem du nun weißt, wie sich Cmdlets verketten lassen, fragst du dich sicherlich wie du herausfinden kannst, welche Cmdlets überhaupt miteinander "kompatibel" sind.
Prinzipiell können Cmdlets verkettet werden, wenn das Ausgabeobjekt des ersten Cmdlets von dem zweiten Cmdlet als Eingabeobjekt akzeptiert wird. Dies geschieht entweder ByValue oder ByPropertyName.
Cmdlets nehmen direkt den Wert des Ausgabeobjekts (OutputObject) des vorherigen Cmdlets als InputObject an, wie in folgendem Beispiel dargestellt:
Get-Service wuauserv | Stop-Service
Um den Typ des OutputObject eines Cmdlets zu ermitteln, kann man wie folgt vorgehen:
Durch die Ausgabe erfahren wir, dass Get-Service den Objekttyp System.ServiceProcess.ServiceController zurückgibt. Es repräsentiert einen Controller, über welchen der dahinterliegende Service angesprochen und gesteuert werden kann.
Um zu prüfen, welche Objekt-Typen von Stop-Service erwartet werden, können wir wie folgt vorgehen:
# Befehl:
Get-Help Stop-Service -Parameter
InputObject
# Ausgabe:
Der Parameter -InputObject für das Cmdlet Stop-Service erwartet einen Eingabewert des Typs System.ServiceProcess.ServiceController[]. Das bedeutet, dass Stop-Service eine Sammlung (ein Array) von ServiceController-Objekten akzeptiert. Wichtig ist hier der Teil "Accept pipeline input? true (ByValue)". Das bedeutet, dass Stop-Service diesen Input direkt aus der Pipeline akzeptiert, wenn er dem erwarteten Typ (Service) entspricht.
Somit wissen wir, dass wir beide Cmdlets verketten können und Stop-Service die ServiceController-Objekte unterstützt (ByValue).
Die Pipeline-Übergabe "ByPropertyName" ist eine andere Art der Verkettung. Hierbei wird der Input für ein Cmdlet nicht auf Basis des Typs des übergebenen Objekts, sondern auf Basis des Namens einer Eigenschaft oder eines Parameters des Objekts bestimmt.
Ein einfaches Beispiel dazu:
'wuauserv'| Stop-Service
In diesem Beispiel wird der Name des Dienstes vom Cmdlet Get-Service an Stop-Service übertragen. Das Cmdlet Stop-Service benötigt normalerweise den Dienstnamen als Eingabe, um einen Dienst zu stoppen.
Um herauszufinden, ob ein Cmdlet die Eingabe "ByPropertyName" akzeptiert, können wir den folgenden Befehl verwenden:
# Befehl:
Get-Help Stop-Service -Parameter Name
# Ausgabe:
Hier sehen wir, dass der Parameter -Name für das Cmdlet Stop-Service eine Eingabe des Typs String[] erwartet, und dass er die Eingabe aus der Pipeline aufgrund des Namens der Eigenschaft akzeptiert (siehe "Accept pipeline input? true (ByPropertyName)").
Das bedeutet, wenn das aus der Pipeline übergebene Objekt eine Eigenschaft namens "Name" hat (was bei Get-Service der Fall ist), dann kann dieses Cmdlet den Wert dieser Eigenschaft nutzen.
In der Praxis sollten wir immer die Dokumentation überprüfen, um sicherzustellen, dass die erwarteten Eingaben und die tatsächlichen Ausgaben eines Cmdlets übereinstimmen, bevor wir sie in einer Pipeline verketteten. Es ist auch wichtig zu beachten, dass viele Cmdlets sowohl "ByValue" als auch "ByPropertyName" unterstützen können, abhängig von den bereitgestellten Daten und den erwarteten Eingaben.
Cmdlets sind oft so konzipiert, dass sie mit ähnlichen Cmdlets in ihrer "Kategorie" oder ihrem Modul kompatibel sind. Zum Beispiel können viele Active Directory-Cmdlets, die User-Objekte ausgeben, mit anderen Active Directory-Cmdlets, die User-Objekte als Eingabe verwenden, in einer Pipeline kombiniert werden.
Letztlich erfordert die effektive Nutzung der Pipeline in PowerShell auch ein gewisses Experimentieren und Erfahrung. Es kann hilfreich sein, mit verschiedenen Cmdlets zu spielen und zu sehen, wie sie in der Praxis miteinander interagieren.
Die Pipeline-Funktionalität in PowerShell stellt ein mächtiges Werkzeug für Administratoren dar und bietet eine effiziente Möglichkeit, verschiedene Aufgaben zu vereinfachen und zu automatisieren. Der Schlüssel zum Verständnis und zur erfolgreichen Anwendung liegt in der konsequenten Auseinandersetzung und Praxis. Einmal gemeistert, wird die Arbeit mit der PowerShell-Pipeline nicht nur die Effizienz steigern, sondern auch die Möglichkeit eröffnen, benutzerdefinierte Lösungen und Funktionen zu schaffen, die genau auf individuelle Bedürfnisse zugeschnitten sind.
Entfalte das volle Potential von PowerShell mit unserem praktischen Poster. Egal ob Anfänger oder erfahrener Profi, dieses Cheat Sheet ist darauf ausgelegt, dein Anlaufpunkt für die wichtigsten und am häufigsten verwendeten Cmdlets zu sein.
Das Poster gibt es zum Download und in Papierform.
Sep 30, 2024 by Frank Kresse
Wir haben unser neuestes ScriptRunner-Update, Version 7.1, veröffentlicht. Dieses Update ist vollgepackt mit...
Aug 16, 2024 by Heiko Brenn
Willkommen im Scriptember! Wir freuen uns, einen ganz besonderen Monat ankündigen zu können: Wir feiern einen Monat...
Aug 14, 2024 by Jeffery Hicks
Wie gut bist du mit dem Thema vertraut? Vielleicht gibt dir dieser Artikel nur einen Überblick. Aus meiner Erfahrung in...
Philip Lorenz ist als DevOps- und Cloud-Engineer tätig. Neben dieser Tätigkeit hält er Schulungen und erstellt Lerninhalte rund um die Themen PowerShell, Automatisierung und Cloud-Computing.