Archiv der Kategorie: PowerShell-Praxis

Praxistipp: Wurden alle Zip-Dateien ausgepackt?

Große Laufwerksdateien können auch als eine Sammlung von kleineren Zip-Dateien zur Verfügung gestellt werden, die alle heruntergeladen, extrahiert und mit einem Tool wie 7Zip zu einer großen Datei oder einer Verzeichnisstruktur zusammengesetzt werden. Da nach dem Extrahieren mehrere Dutzend Zip-Dateien mit einer durchgehenden Nummerierung (z.B. Datei001, Datei002, Datei004 usw.) vorliegen stellt sich die Frage, ob alle Dateien vollständig sind.

Als PowerShell-Einsteiger würde man vielleicht versuchen, ein kleines Skript zu schreiben, das alle Dateien einliest, irgendwie die Nummern aus dem Dateinamen extrahiert und in einem weiteren Schritt z.B. im Rahmen einer Schleife von 1 bis n prüft, ob jede Zahl in der Liste der Dateinamen vorkommt.

Es geht natürlich auch etwas einfacher. Dank dem praktischen Group-Object-Command lässt sich alles in einer Befehlszeile zusammenfassen. Voraussetzung ist, dass sich alle Zip-Dateien im aktuellen Verzeichnis befinden


dir | select-object -expand Name | select-string "\.(\d+)$" | select-object @{n="Nr";e={$_.Matches[0].Groups[1].Value}} | Group-Object Nr | Where Count -eq 1

PowerShell-Remoting mit SSH

PowerShell-Remoting mit SSH ist gut dokumentiert. Zwei sehr gute Artikel sollten für einen erfolgreichen Probelauf genügen:

https://www.thomasmaurer.ch/2020/04/enable-powershell-ssh-remoting-in-powershell-7/

und

https://4sysops.com/archives/enable-powershell-core-6-remoting-with-ssh-transport/

Ein dritter Artikel beschreibt die Verwendung der Public Key-Authentifizierung als Alternative zur Passwort-Eingabe:

https://4sysops.com/archives/powershell-remoting-with-ssh-public-key-authentication/

Was eventuell noch nicht jeder weiß, der sich für das Thema SSH mit PowerShell interessiert. Seit ein paar Monaten gibt es in der PowerShell Gallery ein kleines Modul des PowerShell-Teams, mit dessen einzigem Enable-SSHRemoting-Command das Einrichten von SSH auf dem Remote-Computer sehr einfach wird. Der Eintrag

PasswordAuthentication yes

muss allerdings auch in diesem Fall einkommentiert werden, falls eine Kennwort-Authentifizierung gewünscht ist. Für das erste Kennenlernen ist dies die einfachste Variante.

Das Modul gibt es unter

https://www.powershellgallery.com/packages/Microsoft.PowerShell.RemotingTools/0.1.0

Damit hat es sogar bei mir auf Anhieb funktioniert;)

Insgesamt sind damit folgende Schritte auf dem SSH-Server zu erledigen:

  1. PowerShell 7 installieren
  2. OpenSSH Client und OpenSSH Server installieren
  3. Enable-SSHRemoting ausführen oder den subsystem-Eintrag in der sshd-config-Datei „zu Fuß“ anlegen
  4. sshd-Dienst (nicht ssh) neu starten – unter Linux service ssh restart (eigentlich gar nicht so schwer;)

Damit kann per New-PSSession, Enter-PSSession und Invoke-Command unter einer PowerShell ab Version 6.0 SSH über den SSHTransport-Parameter verwendet werden:

#requires -version 
$hostname="Ubunti
#$hostname="172.23.25.12"
$Username="pemo"
$S1 = New-PSSession -Hostname $Hostname -Username $Username -SSHTransport -Subsystem powershell
Invoke-Command -ScriptBlock { Get-Process} -Session $S1
Remove-PSSession -Session $S1

Der Subsystem-Parameter wählt den Namen des auf dem SSH-Server angelegten subsystem-Eintrag in sshd_config aus. Das Passwort wird bei jedem (!) Aufruf abgefragt. Wer das nicht möchte, muss Public Key-Authentizierung verwenden. Wie das geht, wird in einem der genannten Blog-Artikel beschrieben.

Viel Erfolg!

Abb. Dank snap besteht die Installation der PowerShell unter Ubuntu aus einem Aufruf (sofern sie nicht bereits vorinstalliert ist)

Anlegen einer Custom Rule für Scriptanalyzer

Der PowerShell Scriptanalyzer ist das Werkzeug, um für PowerShell-Skripte mit einfachen Mitteln eine umfassende Qualitätsanalyse durchzuführen.

Eine einer Stärken ist seine Erweiterbarkeit. Durch das Definieren von Custom Rules lassen sich theoretisch beliebige Merkmale eines Skriptes testen (z.B. ob Kommentare irgendwelche unflätigen Begriffe enthalten;).

Grundsätzlich ist das Definieren einer solchen Custom Rule einfach, denn sie besteht nur aus einer Function, die in einer Psm1-Datei abgelegt werden muss. Beim Aufruf von Invoke-ScriptAnalyzer wird der Pfad der Psm1-Datei über den CustomRulePath-Parameter angegeben.

PowerShell-Experte Mathieu Buisson beschreibt in einem sehr guten Blog-Beitrag ein kleines Beispiel, das bei mir auf Anhieb funktioniert hat:

https://mathieubuisson.github.io/create-custom-rule-psscriptanalyzer/

Ich war für sein Beispiel, das man sich lediglich aus dem GitHub-Repo kopieren muss, sehr dankbar, da ich zuvor „stundenlang“ herumprobiert hatte, um eine eigene Regel zum Laufen zu bringen (ich hatte vor Jahren bereits einmal eine Custom Rule als Psm1-Datei erstellt, war aber zu bequem, das Beispiel von damals zu suchen). Was ich auch probiert hatte, das Ergebnis war eine Fehlermeldung, in der behauptet wurde, dass meine psm1-Datei keine Regeln enthielt. Wirklich nervig. Irgendwann kam ich auf die Lösung. Ich hatte offenbar übersehen, dass der Function-Parameter ScriptBlockAst heißen muss. Außerdem müssen die Typen der Input- und Output-Werte genau angegeben werden.

Die größte Herausforderung beim Erstellen einer Custom Rule sind aber nicht die kleinen Formalitäten, sondern der Umstand, dass man sich in Grundzügen mit den Abstract Syntax Trees (AST) der PowerShell auskennen muss.

Meine Regel prüft, ob ein Skript Cmdlets oder Functions enthält, die keinen WhatIf-Parameter anbieten. Warum kann das wichtig sein? Weil das Commands sind, die nicht von der globalen WhatIfPreference-Einstellung betroffen sind. Möchte man ein unbekanntes Skript in einer „Sandbox“ ausführen, in der nichts „Schlimmes“ passieren kann, wären diese Commands davon nicht betroffen.

Auch wenn man in der Regel davon ausgehen kann, dass ein Command ohne WhatIf-Parameter grundsätzlich nichts macht, was negative Folgen haben könnte, 100% sicher kann man sich nicht sein, da der Autor des Cmdlets oder der Functions das Implementieren von Whatif über SupportsShouldProcess = $true im Rahmen von [CmdletBinding()] nicht für erforderlich gehalten oder schlicht vergessen haben könnte.

Wer daher wissen will, welche Commands von einem WhatIf-Modus unbeeindruckt bleiben, sollte diese Regel ausprobieren.

Die gesamte Datei gibt es in meinem GitHub-Repo

https://github.com/pemo11/whatifrule

Ich werde die einzelnen Schritte, insbesondere den AST-Teil, in naher Zukunft noch ausführlicher beschreiben.

Den folgenden Kommentar wollte ich in dem Blog von Mathieu Buisson schreiben, aber aus irgendeinem Grund war das Kommentieren nicht möglich:

Your article is very helpful, thank you – but I think that you should mention that the parameter name has to be ScriptBlockAst otherwise the rule is not found by ScriptAnalyzer by my experience.