Tags: PowerShell, Scripts
In PowerShell verfügen alle Cmdlets über die so genannten Common Parameters. Dazu gehören etwa Erroraction, Verbose oder OutVariable. Nicht alle, aber sehr viele Cmdlets unterstützen zudem die Parameter für das Risiko-Management. Dazu gehören WhatIf und Confirm. Auch Force fällt in diese Kategorie, wenn auch quasi als Gegenspieler der beiden anderen.
Gerade bei sensiblen Operationen wünscht man sich eine Möglichkeit, einen PowerShell-Befehl zu simulieren, um zu sehen, ob er die gewollten Resultate bringt oder womöglich Schaden anrichtet.
Befehl simulieren mit WhatIf
Genau diesem Zweck dient der Parameter WhatIf (Alias "wi"). Man braucht ihn nicht, um die Syntax eines Aufrufs zu prüfen, denn derartige Fehler führen ohnehin zum Abbruch der Operation. Vielmehr untersucht die Simulation einige Eigenschaften der betroffenen Objekte und benennt das voraussichtliche Resultat des Vorgangs.
Wie tief die Analyse reicht, ist jedoch von Cmdlet zu Cmdlet sehr verschieden. Das betrifft zum Beispiel die Berechtigungen zum Ausführen von Befehlen. Versucht man etwa, mit Remove-Item eine Datei ohne ausreichende Rechte zu löschen, dann prüft WhatIf diese nicht vorab.
Betrifft der Löschvorgang hingegen Objekte in der Registry, dann meldet das Cmdlet im Was-wäre-wenn-Modus, dass die nötigen Berechtigungen fehlen. Wenn die Objekte aber nicht existieren, dann erhält man eine entsprechende Fehlermeldung.
Auch wenn die Simulation in vielen Fällen unvollständig ausfällt, ist die Verwendung von WhatIf häufig hilfreich. Leider unterstützen einige heikle Cmdlets diesen Parameter nicht, unter anderem viele aus dem Modul Hyper-V oder GroupPolicy.
Um herauszufinden, welche Cmdlets den Parameter WhatIf unterstützen, greift man zu Get-Command:
Get-Command -ParameterName whatif -Module ActiveDirectory
Dieses Kommando gibt die Cmdlets im Modul ActiveDirectory aus, die man mit WhatIf aufrufen kann. Möchte man wissen, welche diesen Parameter nicht zulassen, dann hilft dieser Befehl weiter:
Get-Command -Module ActiveDirectory |
where {$_.Parameters.keys -notcontains "WhatIf"}
Ausführung bestätigen mit Confirm
Besonders wenn man Befehle auf viele Objekte anwendet und dabei Wildcards einsetzt, besteht die Gefahr, dass es auch die Falschen erwischt. PowerShell kategorisiert daher alle Cmdlets hinsichtlich ihrer Risiken für das System, wobei dieser ConfirmImpact die Werte High, Medium, Low und None haben kann. Letzteres trifft auf rein lesende Cmdlets zu, deren Ausführung niemals bestätigt werden muss. Diese Bewertung lässt sich nicht ändern.
Standardmäßig muss man alle Operationen mit Cmdlets bestätigen, die als High eingestuft sind. Dieses Verhalten wird durch die Variable $ConfirmPreference bestimmt, die mit High vorbelegt ist.
Ändert man ihren Wert auf Medium oder Low, dann muss man bereits die Ausführung von Cmdlets bestätigen, deren Risiko als mittel oder gering gilt:
$ConfirmPreference="low"
Über diese Variable ändert man generell das Verhalten von PowerShell für die betreffende Sitzung. Anstatt pauschal alle Cmdlets auf diese Weise zu begrenzen, kann man individuelle Aufrufe mit dem Parameter Confirm anpassen.
Übergibt man ihm keinen Wert, dann hat dies die gleiche Wirkung wie $true:
del '.\slideshow.pptx' -Confirm
Umgekehrt kann man auch die strengste Einstellung von $ConfirmPreference überschreiben, indem man confirm den Wert $false übergibt:
$ConfirmPreference="low"
del '.\slideshow.pptx' -Confirm:$false
Sinnvoll ist das Abschalten der Bestätigung in Scripts, die in einer nicht interaktiven Umgebung laufen, weil diese sonst in ihrer Ausführung blockiert werden könnten.
Während WhatIf nur in einem Teil der Cmdlets präsent ist, wird Confirm von allen unterstützt, die mit einem der folgenden Verben beginnen:
- Clear
- Disable
- Dismount
- Move
- Remove
- Stop
- Suspend
- Uninstall
Aktionen erzwingen mit Force
Ein Gegenspieler zu Confirm ist in gewisser Hinsicht Force. Es hat zwar keinen Einfluss auf Bestätigungen, aber während das erste eine zusätzliche Hürde für ungewollte Änderungen darstellt, setzt das andere einen Schutz außer Kraft.
Wenn man zum Beispiel eine schreibgeschützte Datei löschen möchte, dann scheitert Remove-Item mit einer irreführenden Meldung ("keine ausreichenden Zugriffsberechtigungen"). Der Schalter Force erzwingt dann das Löschen.
Die Wirkung dieses Parameters hängt vom jeweiligen Cmdlet ab. Bei Out-File führt er beispielsweise dazu, dass eine existierende Datei überschrieben wird. Get-ChildItem hingegen zeigt auch versteckte Dateien an, die normalerweise nicht in der Ausgabe enthalten sind. Aber Force kann natürlich nie fehlende Zugriffsrechte kompensieren.
Zusammenfassung
PowerShell bietet mit dem Schalter WhatIf die Möglichkeit, die Ausführung von Befehlen zu simulieren. Nicht alle Cmdlets unterstützen diesen Parameter und er kann nicht alle Fehler vorwegnehmen, die unter Umständen auftreten werden. Fehlende Berechtigungen werden ebenfalls nicht immer erkannt.
Einen weiteren Schutz vor ungewollten Konsequenzen eines Kommandos bieten Bestätigungen. Diese sind standardmäßig nur erforderlich, wenn Cmdlets als riskant eingestuft sind. Dies lässt sich jedoch über die Variable $ConfirmPreference oder die Verwendung des Schalters confirm ändern.
Einen gegenteiligen Effekt hat hingegen oft der Schalter Force. Seine Bedeutung hängt vom jeweiligen Cmdlet ab, und mit Vorsicht zu genießen ist er nur bei Schreibzugriffen.
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
- ScriptRunner Portal Edition R5: Konfiguration von Abfragen, OpenID-Support, Web-API statt IIS
- ScriptRunner Portal Edition R4: Support für Microsoft Graph, überarbeitetes Portal, zentrale Execution-Policy
- Microsoft Graph: Einheitliches (PowerShell)-API für Microsofts Cloud-Dienste
- Strings ersetzen oder löschen mit PowerShell
- PowerShell 7: Preview 7.1, Update für Secret Management und Visual Studio Code
Weitere Links