Kategorieauswahl

Schnelle Powershell Befehle anhand des Beispiels grep

Hier ein Quick&Dirty Beispiel wie man schnelle Powershellscripte schreibt um die eigenen Scripte ordentlich zu tunen. Unter Powershell gibt es zwar mit select-object und where-object als auch select-string einem grep aus dem UNIX- bzw. LINUX-Bereich ähnliche Befehle, doch so wirklich Bash-Gefühle kommen dabei nicht auf. Einen ersten Turbo können Sie einschalten, wenn Sie Parameter wie -inculde, -exclude oder -filter des jeweiligen Befehls verwenden, statt den Befehl alle Informationen beschaffen zu lassen und diese hinterher mit dem where-object auszuwerten. Vielleicht kennen Sie die Möglichkeit eine Funktion zu schreiben. Schneller funktioniert aufgrund des Streaming-Modus jedoch ein Filter. Wenn Sie dasselbe Script noch einmal mit dem Stichwort function statt filter einleiten können Sie das Laufzeitverhalten sehr schön überprüfen indem Sie den Befehl ls c: -recurse | grep suchbegriff aufrufen. Schauen Sie sich auch im Taskmanager ruhig einmal den Speicherverbrauch an!

filter grep ($suchbegriff) {
 $_  | out-string -stream | select-string $suchbegriff
 # Etwas aufwändiger, doch dafür werden die Objekte nicht als String, sondern nach wie vor als Objekt zurück gegeben mit folgender Zeile: # if (@($_  | out-string -stream | select-string $suchbegriff -simplematch).count -gt 0) {$_} }
Bei function wird der Befehl vor der Pipe erst einmal alle Daten (im obigen Beispiel alle Dateinamen) in einen Puffer schreiben. Erst wenn alle Dateien von Lw. C: im Puffer sind wird dieser an die Funktion nach der Pipe übergeben. Das out-string -stream hat damit allerdings nichts zu tun! Durch die Einleitung mit filter nimmt unser grep allerdings schon die Eingaben von ls entgegen sobal der erste Dateiname vorliegt. Die beiden Kommandos arbeiten also parallel. Das führt zu weniger Speicherverbrauch und zu schnelleren Ergebnissen.

Wer das Tuning auf die Spitze treiben möchte greift dennoch wieder zu einer Funktion. Denn filter schreibt auch eine function nur bettet er automatisch den kompletten Code in einen process Block ein. Das Beispiel:

function {
  process{
   # mein code
  }
}

ist also dasselbe wie:

filter {
  # mein code
}

In Ihrer Funktion gibt es aber vielleicht Dinge die nur 1 x zu Beginn und 1 x am Ende durchgeführt werden müssen, während die eigentliche Verarbeitung für alle übergebenen Objekte durchgeführt werden müssen. Bei einem filter würde immer komplett alles durchlaufen werden.

function {
  begin {
   # Hier könnten Sie z. B. den aktuellen Verzeichnispfad, oder andere Ausgangsbedingungen in eine Variable retten bevor Sie zu wüten anfangen
  }
  process {
   # Hier findet die eigentlich Verarbeitung statt. Möglicher Weise benutzen Sie cd um Verzeichnisse zu wechseln etc...
  }
  end {
   # Wechseln Sie wieder in das ursprüngliche Verzeichnis zurück geben Sie Variablen frei und führen Sie weitere "Aufräumvorgänge" durch
  }
}

Der Code bei begin würde also bei der ersten Objektübergabe erfolgen. Für alle weiteren Objekte würde nur noch der Code im Bereich process ausgeführt werden. Nach der Verarbeitung des letzten Objekts würde schließlich der Code unter end ausgeführt werden.

Möchten Sie Ihre Funktion dauerhaft verfügbar haben, sollten Sie diesen in eine Datei namens profile.ps1 schreiben und im Verzeichnis C:\Windows\System32\WindowsPowerShell\v1.0 ablegen, wenn er allen Benutzern des Computers zur Verfügung stehen soll. Wenn es nur für Ihren Benutzer sein soll, dann unter C:\Users\Ihr Benutzername\Documents\WindowsPowerShell.

Wenn Sie Daten von anderen Computern sammeln und auswerten, dann lassen Sie die Auswertung auf den anderen PCs laufen und holen Sie sich nur die Ergebnisdaten ab.

Langsam:

invoke-command {get-process} -computer name1,name2,name3 | where-object {$_.VM -gt 30MB} | sort PSComputerName | select Name,VM

Schnell:

invoke-command {get-process | select Name,VM | where-object {$_.VM -gt 30MB}} -computer name1,name2,name3 | sort PSComputerName

Des Weiteren gibt es für invoke-command den Parameter -throttlelimit. Dieser gibt an wieviele Computer gleichzeitig abgefragt werden. Der Standardwert ist 32. Je nach Aufgabe kann es sich lohnen mehr oder weniger Rechner anzugeben.

Der Befehl measure-command {Ihre Befehle oder Script} gibt Auskunft über die Zeit die Ihr Script zur Ausführung gebraucht hat.

Anregungen und Kommentare erwünscht