PowerShell für Sysadmins

BildHallo, Bewohner! PowerShell ist sowohl eine Skriptsprache als auch eine Befehlsshell, mit der Sie nahezu jede Aufgabe verwalten und automatisieren können. In PowerShell for Sysadmins zeigt Ihnen Microsoft MVP-Besitzer Adam Bertram alias „The Automator“, wie Sie PowerShell verwenden, damit der Leser endlich Zeit für Spielzeug, Yoga und Katzen hat. Sie lernen: - Befehle kombinieren, den Ausführungsfluss steuern, Fehler behandeln, Skripte schreiben, sie remote ausführen und sie mit dem Pester-Testframework testen. - Analysieren Sie strukturierte Daten wie XML und JSON, arbeiten Sie mit gängigen Diensten (wie Active Directory, Azure und Amazon Web Services) und erstellen Sie Serverüberwachungssysteme. -Erstellen und entwerfen Sie PowerShell-Module. - Verwenden Sie PowerShell für bequeme,vollautomatische Windows-Installation. - Erstellen Sie eine Active Directory-Gesamtstruktur mit nur einem Hyper-V-Host und einigen ISO-Dateien. - Erstellen Sie unzählige Web- und SQL-Server mit nur wenigen Codezeilen! Beispiele aus der Praxis helfen dabei, die Lücke zwischen Theorie und Arbeit in einem realen System zu schließen, und der leichte Humor des Autors erleichtert das Lesen. Verlassen Sie sich nicht mehr auf teure Software und vage Ratschläge aus dem Internet!



Für wen ist dieses Buch?
- , . DevOps, , / (CI/CD).



, PowerShell . PowerShell « Windows» — Microsoft, PowerShell . , , .



Kontrollfluss



Lassen Sie uns ein wenig wiederholen. In Kapitel 3 haben wir gelernt, wie Sie Befehle mithilfe einer Pipeline und externer Skripts kombinieren können. In Kapitel 2 wurden Variablen und ihre Verwendung zum Speichern von Werten behandelt. Einer der Hauptvorteile der Arbeit mit Variablen ist die Möglichkeit, mit ihnen Code zu schreiben, der nicht mit Wert, sondern mit "Bedeutung" arbeitet. Anstatt beispielsweise mit der Nummer 3 zu arbeiten, arbeiten Sie mit dem allgemeinen Konzept von $ serverCount. Auf diese Weise können Sie Code schreiben, der unabhängig von einem, zwei oder tausend Servern gleich funktioniert. Kombinieren Sie diese Fähigkeit mit der Fähigkeit, Ihren Code in Skripten zu speichern, die auf verschiedenen Computern ausgeführt werden können, und Sie können Probleme in einem viel größeren Maßstab lösen.



Im Leben ist es jedoch manchmal wichtig, ob Sie mit einem Server, mit zwei oder mit tausend arbeiten. Bisher haben Sie keine geeignete Möglichkeit, dies zu berücksichtigen, und Ihre Skripte werden einfach von oben nach unten ausgeführt und können sich aufgrund bestimmter Werte nicht anpassen. In diesem Kapitel werden wir den Kontrollfluss und die bedingte Logik verwenden, um Skripte zu schreiben, die abhängig von den Werten, mit denen sie arbeiten, unterschiedliche Befehle ausführen. Am Ende des Kapitels erfahren Sie, wie Sie if / then- und switch-Anweisungen sowie verschiedene Schleifen verwenden, um Ihrem Code die dringend benötigte Flexibilität zu geben.



Ein wenig über den Kontrollfluss



Wir werden ein Skript schreiben, das den Inhalt einer Datei liest, die auf mehreren Remotecomputern gespeichert ist. Laden Sie zum Fortfahren eine Datei mit dem Namen App_configuration.txt aus den Materialien des Buches unter github.com/adbertram/PowerShellForSysadmins/ herunter und platzieren Sie sie im Stammverzeichnis des Laufwerks C: \ auf mehreren Remotecomputern. Wenn Sie keine Remotecomputer haben, lesen Sie erst einmal weiter. In diesem Beispiel verwende ich die Server mit den Namen SRV1, SRV2, SRV3, SRV4 und SRV5.



Um auf den Inhalt der Datei zuzugreifen, verwenden Sie den Befehl Get-Content und geben Sie den Pfad zur Datei im Wert des Parameterarguments Path an, wie unten gezeigt:



Get-Content -Path "\\ Servername \ c $ \ App_configuration.txt ""



Speichern wir zunächst alle Namen unserer Server in einem Array und führen diesen Befehl für jeden Server aus. Öffnen Sie eine neue .ps1-Datei und geben Sie den Code aus Listing 4.1 ein.



Listing 4.1. Extrahieren von Dateiinhalten von mehreren Servern



$servers = @('SRV1','SRV2','SRV3','SRV4','SRV5')
Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[1])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[2])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[3])\c$\App_configuration.txt"
Get-Content -Path "\\$($servers[4])\c$\App_configuration.txt"
      
      





Theoretisch sollte dieser Code ohne Probleme funktionieren. In diesem Beispiel wird jedoch davon ausgegangen, dass für Sie etwas schief geht. Was ist, wenn der SRV2-Server nicht verfügbar ist? Was ist, wenn jemand vergessen hat, App_configuration.txt auf SRV4 zu setzen? Oder hat vielleicht jemand den Dateipfad geändert? Sie können für jeden Server ein separates Skript schreiben, diese Lösung lässt sich jedoch nicht skalieren, insbesondere wenn Sie mehr und mehr Server hinzufügen. Sie benötigen Code, der je nach Situation funktioniert.



Die Idee hinter dem Kontrollfluss ist, dass Sie verschiedene Befehlssätze basierend auf vordefinierter Logik ausführen können. Stellen Sie sich vor, Ihre Skripte werden entlang eines bestimmten Pfades ausgeführt. Bisher ist Ihr Pfad einfach - von der ersten bis zur letzten Codezeile. Sie können jedoch unterwegs Gabeln hinzufügen, zu Orten zurückkehren, die Sie bereits besucht haben, oder darüber springen. Durch das Verzweigen der Ausführungspfade Ihres Skripts erhalten Sie mehr Flexibilität, sodass Sie viele Situationen mit einem einzigen Skript bewältigen können.



Zunächst betrachten wir die einfachste Art des Kontrollflusses, die bedingte Anweisung.



Bedingte Anweisungen verwenden



In Kapitel 2 haben wir gelernt, dass es logische Werte gibt: wahr und falsch. Mit Booleschen Werten können Sie bedingte Anweisungen erstellen, die PowerShell anweisen, einen bestimmten Codeblock auszuführen, je nachdem, ob ein Ausdruck (als Bedingung bezeichnet) als wahr oder falsch ausgewertet wird. Eine Bedingung ist eine Ja / Nein-Frage. Haben Sie mehr als fünf Server? Läuft Server 3? Existiert der Dateipfad? Um mit der Verwendung von bedingten Anweisungen zu beginnen, sehen wir uns an, wie solche Fragen in Ausdrücke konvertiert werden.



Erstellen von Ausdrücken mit Operatoren Sie



können logische Ausdrücke mit Vergleichsoperatoren schreiben, die Werte vergleichen. Um einen Vergleichsoperator zu verwenden, müssen Sie ihn zwischen zwei Werten platzieren, zum Beispiel:



PS> 1 –eq 1
True
      
      





In diesem Fall können Sie mit dem Operator –eq die Äquivalenz zweier Werte bestimmen.

Nachfolgend finden Sie eine Liste der am häufigsten verwendeten Vergleichsoperatoren:



-eq vergleicht zwei Werte und gibt True zurück, wenn sie gleich sind.



-ne vergleicht zwei Werte und gibt True zurück, wenn sie nicht gleich sind.



-gt vergleicht zwei Werte und gibt True zurück, wenn der erste größer als der zweite ist.



-ge vergleicht zwei Werte und gibt True zurück, wenn der erste größer oder gleich dem zweiten ist.



-lt vergleicht zwei Werte und gibt True zurück, wenn der erste kleiner als der zweite ist.



-le vergleicht zwei Werte und gibt True zurück, wenn der erste kleiner oder gleich dem zweiten ist.



-contains gibt True zurück, wenn der zweite Wert Teil des ersten ist. Mit diesem Operator können Sie beispielsweise bestimmen, ob sich ein Wert in einem Array befindet.



PowerShell verfügt auch über erweiterte Vergleichsoperatoren. Wir werden hier nicht weiter darauf eingehen , aber ich empfehle, dass Sie sie in der Microsoft-Dokumentation unter docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators oder in der PowerShell-Hilfe lesen (siehe Kapitel 1).



Mit den obigen Operatoren können Sie Variablen und Werte vergleichen. Aber der Ausdruck muss kein Vergleich sein. Manchmal können PowerShell-Befehle als Bedingungen verwendet werden. Im vorherigen Beispiel wollten wir die Serververfügbarkeit kennen. Mit dem Cmdlet Test-Connection können Sie die Verbindung zum Server testen. Normalerweise enthält die Ausgabe des Cmdlets Test-Connection viele verschiedene Informationen. Mit dem Parameter Quiet können Sie den Befehl erzwingen, True oder False zurückzugeben, und der Parameter Count kann den Test auf einen Versuch beschränken.



PS> Test-Connection -ComputerName offlineserver -Quiet -Count 1
False
      
      





PS> Test-Connection -ComputerName onlineserver -Quiet -Count 1
True
      
      





Um herauszufinden, ob der Server nicht verfügbar ist, können Sie den Ausdruck –not verwenden, um den Ausdruck umzukehren:



PS> -not (Test-Connection -ComputerName offlineserver -Quiet -Count 1)
True
      
      





Nachdem Sie mit den grundlegenden Ausdrücken vertraut sind, schauen wir uns den einfachsten bedingten Operator an.



Die if-Anweisung



Die if-Anweisung funktioniert einfach: Wenn X wahr ist, dann mache Y. Das war's!



Um eine Anweisung in einem Ausdruck zu verwenden, schreiben Sie das Schlüsselwort if gefolgt von Klammern, die die Bedingung enthalten. Dem Ausdruck folgt ein Codeblock in geschweiften Klammern. PowerShell führt diesen Codeblock nur aus, wenn der Ausdruck True ergibt. Wenn der if-Ausdruck False ergibt oder überhaupt nichts zurückgibt, wird der Codeblock nicht ausgeführt. Die Syntax für die if / then-Anweisung ist in Listing 4.2 dargestellt.



Listing 4.2. If-Anweisungssyntax



if () {
   #  ,   
}
      
      





Dieses Beispiel hat eine neue Syntax: Das Hash-Zeichen (#) kennzeichnet einen Kommentar - dies ist Text, den PowerShell ignoriert. Sie können Kommentare verwenden, um hilfreiche Notizen und Beschreibungen für sich selbst oder eine andere Person zu hinterlassen, die später Ihren Code liest.



Schauen wir uns nun den in Listing 4.1 gezeigten Code noch einmal an. Ich zeige Ihnen, wie Sie eine if-Anweisung verwenden, um zu vermeiden, dass Sie versuchen, einen toten Server zu erreichen. Wir haben bereits im vorherigen Abschnitt gesehen, dass der Befehl Test-Connection als Ausdruck verwendet werden kann, der True oder False zurückgibt. Lassen Sie uns Test-Connection zunächst in eine if-Anweisung einschließen und dann den Befehl Get-Content verwenden, um den Zugriff zu vermeiden ein toter Server. ... Im Moment ändern wir nur den Code für den ersten Server, wie in Listing 4.3 gezeigt.



Listing 4.3. Verwenden einer if-Anweisung für den selektiven Zugriff



$servers = @('SRV1','SRV2','SRV3','SRV4','SRV5')
if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
}
Get-Content -Path "\\$($servers[1])\c$\App_configuration.txt"
----
      
      





Da Ihre if-Anweisung Get-Content enthält, treten beim Versuch, auf einen defekten Server zuzugreifen, keine Fehler auf. Wenn der Test fehlschlägt, versucht Ihr Skript nicht, die Datei zu lesen. Der Code versucht nur dann, auf den Server zuzugreifen, wenn er bereits weiß, dass er aktiviert ist. Beachten Sie jedoch, dass dieser Code nur ausgelöst wird, wenn die Bedingung erfüllt ist. Sehr oft müssen Sie ein Skriptverhalten für eine wahre Bedingung und ein anderes für eine falsche Bedingung angeben. Im nächsten Abschnitt erfahren Sie, wie Sie das Verhalten für eine falsche Bedingung mithilfe der else-Anweisung definieren.



Sonst Aussage



Um Ihrer if-Anweisung eine Alternative zu bieten, können Sie das Schlüsselwort else nach der schließenden Klammer des if-Blocks verwenden, gefolgt von einem weiteren Paar geschweifter Klammern, die den Codeblock enthalten. Wie in Listing 4.4 gezeigt, verwenden wir eine else-Anweisung, um einen Fehler an die Konsole zurückzugeben, wenn der erste Server nicht antwortet.



Listing 4.4. Verwenden der else-Klausel zum Ausführen von Code, wenn die Bedingung

nicht erfüllt ist



if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   Get-Content -Path "\\$($servers[0])\c$\App_configuration.txt"
} else {
   Write-Error -Message "The server $($servers[0]) is not responding!"
}
      
      





Die if / else-Anweisung funktioniert hervorragend, wenn Sie zwei sich gegenseitig ausschließende Situationen haben. In diesem Fall ist der Server entweder verbunden oder nicht, dh wir benötigen nur zwei Zweige des Codes. Mal sehen, wie man mit komplexeren Situationen umgeht.



Elseif Aussage



Die else-Anweisung deckt die umgekehrte Situation ab: Wenn dies nicht funktioniert, tun Sie es trotzdem. Dieser Ansatz funktioniert für binäre Bedingungen, dh wenn der Server entweder ausgeführt wird oder nicht. Aber manchmal muss man sich mit einer Vielzahl von Optionen auseinandersetzen. Angenommen, Sie haben einen Server, der nicht über die gewünschte Datei verfügt, und Sie haben den Namen dieses Servers in der Variablen $ problemServer gespeichert (fügen Sie diese Codezeile Ihrem Skript hinzu!). Dies bedeutet, dass Sie eine zusätzliche Überprüfung benötigen, um festzustellen, ob der Server, den Sie gerade abfragen, der Problemserver ist. Dies kann mit verschachtelten if-Anweisungen erreicht werden, wie im folgenden Code gezeigt:



if (Test-Connection -ComputerName $servers[0] -Quiet -Count 1) {
   if ($servers[0] –eq $problemServer) {
      Write-Error -Message "The server $servers[0] does not have the right
         file!"
   } else {
      Get-Content -Path "\\$servers[0]\c$\App_configuration.txt"
   }
} else {
   Write-Error -Message "The server $servers[0] is not responding!"
}
----
      
      





Es gibt jedoch eine bessere Möglichkeit, dieselbe Logik mit einer elseif-Anweisung zu implementieren, mit der Sie eine zusätzliche Bedingung überprüfen können, bevor Sie zum else-Block zurückkehren. Die Syntax für den elseif-Block ist identisch mit der Syntax für den if-Block. Führen Sie den Code in Listing 4.5 aus, um den Problemserver mit der elseif-Anweisung zu testen.



Listing 4.5. Verwenden des elseif-Blocks



if (-not (Test-Connection -ComputerName $servers[0] -Quiet -Count 1)) { 
   Write-Error -Message "The server $servers[0] is not responding!"
} elseif ($servers[0] –eq $problemServer) 
   Write-Error -Message "The server $servers[0] does not have the right file!"
} else {
   Get-Content -Path "\\$servers[0]\c$\App_configuration.txt"
}
----
      
      





Bitte beachten Sie, dass wir nicht nur eine elseif-Anweisung hinzugefügt, sondern gleichzeitig die Logik des Codes geändert haben. Mit dem Operator –not können wir jetzt überprüfen, ob der Server offline ist. Sobald wir den Netzwerkstatus des Servers ermittelt haben, prüfen wir, ob dies problematisch ist. Wenn nicht, verwenden wir die else-Anweisung, um das Standardverhalten beim Auschecken von Dateien auszulösen. Wie Sie sehen, gibt es verschiedene Möglichkeiten, Ihren Code auf diese Weise zu strukturieren. Wichtig ist, dass der Code funktioniert und für eine Person von außen lesbar ist, unabhängig davon, ob Ihr Kollege ihn zum ersten Mal sieht oder Sie selbst einige Zeit nach dem Schreiben.



Sie können beliebig viele elseif-Anweisungen verketten, um den unterschiedlichsten Umständen gerecht zu werden. Andernfalls schließen sich elseif-Anweisungen gegenseitig aus: Wenn eines der elseifs True ergibt, führt PowerShell nur seinen Code aus und sucht nicht nach anderen Fällen. In Listing 4.5 verursachte dies keine Probleme, da Sie den Server erst nach Überprüfung des Zustands auf "Probleme" testen mussten. In Zukunft empfehle ich Ihnen jedoch, diese Funktion zu berücksichtigen.



Die Anweisungen if, else und elseif eignen sich hervorragend zum Implementieren von Code-Antworten auf einfache Ja / Nein-Fragen. Im nächsten Abschnitt erfahren Sie, wie Sie mit komplexerer Logik arbeiten.



Switch-Anweisung



Lassen Sie uns unser Beispiel ein wenig optimieren. Angenommen, wir haben fünf Server, und auf jedem Server ist der Pfad zur erforderlichen Datei unterschiedlich. Basierend auf dem, was Sie jetzt wissen, müssen Sie für jeden Server eine separate elseif-Anweisung erstellen. Dies wird funktionieren, aber es gibt eine bequemere Methode.



Bitte beachten Sie, dass wir jetzt mit einer anderen Art von Zustand arbeiten werden. Wenn wir früher Antworten auf Fragen wie "Ja / Nein" brauchten, wollen wir jetzt die spezifische Bedeutung einer Sache herausfinden. Ist es ein SRV1-Server? SRV2? Usw. Wenn Sie nur mit einem oder zwei bestimmten Werten arbeiten würden, würde eine if-Anweisung funktionieren. In diesem Fall funktioniert eine switch-Anweisung jedoch viel besser.



Mit der switch-Anweisung können Sie je nach Wert unterschiedliche Codeteile ausführen. Es besteht aus dem Schlüsselwort switch, gefolgt von einem Ausdruck in Klammern. Innerhalb des Schalterblocks befindet sich eine Reihe von Anweisungen, die wie folgt aufgebaut sind: Zuerst geben Sie den Wert an, gefolgt von einer Reihe geschweifter Klammern, die den Codeblock enthalten, und schließlich den Standardblock, wie in Listing 4.6 gezeigt.



Listing 4.6. Anweisungsvorlage wechseln



switch () {
    {
      # 
   }
    {
   }
   default {
     # ,     
   }
}
      
      





Eine switch-Anweisung kann eine nahezu unbegrenzte Anzahl von Werten enthalten. Wenn der Ausdruck einen Wert ergibt, wird der entsprechende Code innerhalb des Blocks ausgeführt. Wichtig ist, dass PowerShell im Gegensatz zu elseif nach Ausführung eines Codeblocks weiterhin den Rest der Bedingungen überprüft, sofern nicht anders angegeben. Wenn keiner der Werte übereinstimmt, führt PowerShell den Code im Standardblock aus. Verwenden Sie das Schlüsselwort break am Ende des Codeblocks, um die Iteration über Bedingungen in einer switch-Anweisung zu beenden (siehe Listing 4.7).



Listing 4.7. Verwenden des Schlüsselworts break in einer switch-Anweisung



switch () {
    {
      # 
      break
   }
----
      
      





Mit dem Schlüsselwort break können Sie Bedingungen in einer switch-Anweisung festlegen, die sich gegenseitig ausschließen. Kehren wir zu unserem Beispiel mit fünf Servern und derselben Datei mit unterschiedlichen Pfaden zurück. Sie wissen, dass der Server, mit dem Sie arbeiten, nur einen Wert haben kann (dh, er kann nicht gleichzeitig als SRV1 und SRV2 bezeichnet werden). Daher müssen Sie break-Anweisungen verwenden. Ihr Skript sollte ungefähr so ​​aussehen wie in Listing 4.8.



Listing 4.8. Überprüfen verschiedener Server mit einer switch-Anweisung



$currentServer = $servers[0]
switch ($currentServer) {
   $servers[0] {
      # Check if server is online and get content at SRV1 path.
      break
   }
   $servers[1] {
      ## Check if server is online and get content at SRV2 path.
      break
   }
   $servers[2] {
      ## Check if server is online and get content at SRV3 path.
      break
   }
----
      
      





Sie können diesen Code nur mit if- und elseif-Anweisungen umschreiben (und ich empfehle Ihnen wirklich, dies zu versuchen!). Unabhängig davon, für welche Methode Sie sich entscheiden, benötigen Sie für jeden Server in der Liste dieselbe Struktur. Dies bedeutet, dass Ihr Szenario ziemlich lang sein wird. Stellen Sie sich vor, Sie testen fünfhundert Server anstelle von fünf. Im nächsten Abschnitt erfahren Sie, wie Sie dieses Problem mithilfe einer der grundlegendsten Kontrollflussstrukturen - einer Schleife - beseitigen können.



Schleifen verwenden



Es gibt eine gute Faustregel für die Computerarbeit: Wiederholen Sie sich nicht (DRY). Wenn Sie den gleichen Job machen, gibt es wahrscheinlich eine Möglichkeit, ihn zu automatisieren. Das Gleiche gilt für die Codierung: Wenn Sie immer wieder dieselben Zeilen verwenden, gibt es wahrscheinlich eine bessere Lösung.



Eine Möglichkeit, Wiederholungen zu vermeiden, ist die Verwendung von Schleifen. In einer Schleife können Sie Code wiederholt ausführen, bis sich eine bestimmte Bedingung ändert. Die Stoppbedingung kann die Schleife eine bestimmte Anzahl von Malen starten, entweder bis sich ein boolescher Wert ändert, oder die Schleife so definieren, dass sie unbegrenzt ausgeführt wird. Wir werden jeden Durchgang der Schleife eine Iteration nennen.



PowerShell bietet fünf Arten von Schleifen: foreach, for, do / while, do / till und while. In diesem Abschnitt werden die einzelnen Schleifentypen erläutert, ihre einzigartigen Funktionen hervorgehoben und die besten Situationen für ihre Verwendung hervorgehoben.



Über den Autor



Adam Bertram ist ein erfahrener IT- und Internet-Business-Experte mit 20 Jahren Erfahrung. Unternehmer, IT-Influencer, Microsoft MVP, Blogger, Schulungsmanager und Content-Marketing-Autor, der mit vielen IT-Unternehmen zusammenarbeitet. Adam gründete auch die beliebte TechSnips-Plattform zur Entwicklung der Fähigkeiten von IT-Fachleuten (techsnips.io).



Weitere Details zum Buch finden Sie auf der Website des Verlags

» Inhaltsverzeichnis

» Auszug



Für Habitors 25% Rabatt auf den Gutschein - PowerShell



Nach Zahlung der Papierversion des Buches wird ein E-Book an die E-Mail gesendet.



All Articles