„Mal schnell ein Script geschrieben“ — Das ist im ersten Moment trivial. Ein oft wiederholender Task soll automatisiert werden, eigentlich keine große Sache. Das Script ist schnell erstellt und läuft die ersten 2 Wochen ohne Probleme.

Doch dann ändern sich die äußeren Einflüsse geringfügig; Ein Ordner wird umbenannt, eine Server-IP ändert sich, eine Datei enthält Leerzeichen oder Sonderzeichen, die Festplatte läuft voll, oder die Netzwerkverbindung zum Backup-Server ist temporär nicht vorhanden. Fälle, die im ersten Moment nicht bedacht wurden, führen bei Shell-Scripts nicht selten zu weitreichenderen Problemen als man anfangs vermutet. Hier ein kleines Beispiel:

[gist id=1780861]

Wird dieses überschaubare Script fälschlicherweise mit ./cleanup.sh tmp statt mit ./cleanup /tmp aufgerufen (führender Slash vergessen), passiert folgendes: Der cd-Befehl erhält als ersten Parameter den durchgereichten Pfad ($1) und versucht das aktuelle Verzeichnis zu wechseln. Dies schlägt fehl und der cd-Befehl gibt eine Fehlermeldung aus. Das Shellscript cleanup.sh läuft weiter, da dieses bis jetzt noch keinen Fehler produziert hat (der cd-Befehl produzierte den Fehler, nicht das Shellscript). Der nächste Befehl wird ausgeführt und löscht alles aus dem aktuellen Verzeichnis. Wird das Script im Wurzelverzeichnis / ausgeführt, hat das weitreichende Folgen.

Um dieser Problematik vorzubeugen, gibt es mehrere Methoden. Drei davon werden im Folgenden vorgestellt.

Die Shell bei einem Fehler beenden

Bei den bekanntesten Shells (sh, bash, zsh) gibt es die Option set -e. Wird diese gesetzt, wird die komplette Shell sofort terminiert, sobald ein von der Shell ausgeführter Befehl einen Exit-Status ungleich 0 zurückliefert. Da beim Starten eines Shellscripts eine Subshell geöffnet wird, ist dies eine gute Möglichkeit, das Script vorzeitig zu beenden, bevor es Schaden anrichtet. Es lohnt sich also, set -e an den Anfang jedes Shellscripts zu schreiben.

Boolsche Ausdrücke verwenden

Eine weitere Technik ist die Verwendung von boolescher Logik und deren Eigenschaften. Wird A || B ausgeführt, wird B nur dann ausgeführt wenn A false ist. Liefert A true, wird B nicht aufgeführt, da bei einem boolschen „or“ nur eines zutreffen muss (und somit der Fall B garnicht berücksichtigt werden muss). Nutzt man diese Eigenschaft, kann man das Script folgendermaßen aufbauen.

[gist id=1780999]

Schlägt der cd-Befehl fehl (false), so wird die zweite Bedingung ausgeführt — in diesem Falle exit 1, was das Script an dieser Stelle beendet. Mit dieser Methode könnte man sogar noch eine sprechendere Fehlermeldung ausgeben oder Korrekturen vornehmen, um das Script dennoch fortzuführen.

Die äußeren Einflüsse verlässlicher machen

Dies ist natürlich in den seltensten Fällen 100% möglich. Es gibt immer Fälle, die noch nicht bedacht oder vorgesehen sind. Dennoch lässt sich mit ein paar Zeilen Code das Script robuster und strapazierfähiger gestalten. Bei den Übergabeparametern beispielsweise ist es sinnvoll, zu prüfen ob sie in der richtigen/benötigten Anzahl vorliegen und was sie enthalten. Ein einfacher Check wäre folgender:

[gist id=1781053]

Ist die Anzahl der Parameter nicht 1, wird ein Warnhinweis ausgegeben und das Script beendet. So wird sichergestellt, dass der Benutzer garantiert die richtige Anzahl an Parametern angibt. Was der Parameter enthält, und ob es sich wirklich um einen gültigen Pfad handelt, kann mit einem weiteren Check geprüft werden.

Sobald ein Script einmal im Einsatz ist, taucht es erst wieder in Erscheinung, wenn es mit seiner verändernden Umwelt kollidiert. Als Admin und Programmierer hat man also die Aufgabe, Scripte so robust wie möglich zu machen, dass sie so lange wie möglich unbemerkt bleiben.

0 Kommentare

Dein Kommentar

An Diskussion beteiligen?
Hinterlasse uns Deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.