set -eBeendet das Skript, wenn ein Exit-Code ungleich Null auftritt, außer unter bestimmten Bedingungen. Um die Gefahren seines Gebrauchs in wenigen Worten zusammenzufassen: Es verhält sich nicht so, wie die Leute denken, dass es es tut.
Meiner Meinung nach sollte es als gefährlicher Hack angesehen werden, der nur noch aus Kompatibilitätsgründen existiert. Die set -eAnweisung wandelt die Shell nicht von einer Sprache, die Fehlercodes verwendet, in eine Sprache um, die einen ausnahmeartigen Steuerungsfluss verwendet. Sie versucht lediglich, dieses Verhalten nur schlecht zu emulieren.
Greg Wooledge hat viel zu den Gefahren von set -e:
Im zweiten Link gibt es verschiedene Beispiele für das unintuitive und unvorhersehbare Verhalten von set -e.
Einige Beispiele für das nicht intuitive Verhalten von set -e(einige stammen aus dem obigen Wiki-Link):
set -e
x = 0
lass x ++
echo "x ist $ x"
Das Obige bewirkt, dass das Shell-Skript vorzeitig beendet wird, da let x++0 zurückgegeben wird, was vom letSchlüsselwort als falscher Wert behandelt und in einen Exit-Code ungleich Null umgewandelt wird. set -ebemerkt dies und beendet das Skript unbemerkt.
set -e
[-d / opt / foo] && echo "Warnung: foo ist bereits installiert. Wird überschrieben." > & 2
echo "Installiere foo ..."
Das oben beschriebene Verfahren funktioniert wie erwartet und gibt eine Warnung aus, falls diese /opt/foobereits vorhanden ist.
set -e
check_previous_install () {
[-d / opt / foo] && echo "Warnung: foo ist bereits installiert. Wird überschrieben." > & 2
}
check_previous_install
echo "Installiere foo ..."
Das Obige endet, obwohl der einzige Unterschied darin besteht, dass eine einzelne Zeile in eine Funktion umgestaltet wurde, wenn /opt/fooes nicht existiert. Dies liegt daran, dass die Tatsache, dass es ursprünglich funktionierte, eine besondere Ausnahme von seinem set -eVerhalten darstellt. Wenn der a && bWert ungleich Null ist, wird er von ignoriert set -e. Da es sich jedoch um eine Funktion handelt, entspricht der Exit-Code der Funktion dem Exit-Code dieses Befehls, und die Funktion, die einen Wert ungleich Null zurückgibt, beendet das Skript im Hintergrund.
set -e
IFS = $ '\ n' read -d '' -r -a config_vars <config
Das obige liest das Array config_varsaus der Datei config. Wie der Autor vielleicht beabsichtigt, wird es mit einem Fehler beendet, wenn configes fehlt. Da der Autor möglicherweise nicht beabsichtigt, wird er stillschweigend beendet, wenn er confignicht in einer neuen Zeile endet. Wenn set -ehier nicht verwendet config_varswürde , würden alle Zeilen der Datei enthalten sein, unabhängig davon, ob sie in einer neuen Zeile endete oder nicht.
Benutzer von Sublime Text (und anderen Texteditoren, die falsch mit Zeilenumbrüchen umgehen) sollten aufpassen.
set -e
should_audit_user () {
lokale Gruppe groups = "$ (groups" $ 1 ")"
für Gruppe in $ Gruppen; machen
if ["$ group" = audit]; dann gebe 0 zurück; fi
getan
return 1
}
if should_audit_user "$ user"; dann
Logger 'Blah'
fi
Der Autor kann davon ausgehen, dass $userder groupsBefehl fehlschlägt , wenn der Benutzer aus irgendeinem Grund nicht vorhanden ist, und das Skript beendet wird, anstatt den Benutzer eine Aufgabe ungeprüft ausführen zu lassen. In diesem Fall wird die set -eKündigung jedoch niemals wirksam. Wenn $userdas Skript aus irgendeinem Grund nicht gefunden werden kann, gibt die should_audit_userFunktion nur falsche Daten zurück, als wäre sie set -enicht in Kraft.
Dies gilt für alle Funktionen, die aus dem Bedingungsteil einer ifAnweisung aufgerufen werden , unabhängig davon, wie tief sie verschachtelt sind, unabhängig davon, wo sie definiert sind, auch wenn Sie set -esie erneut ausführen . Wenn Sie ifzu einem beliebigen Zeitpunkt verwenden, wird der Effekt vollständig deaktiviert, set -ebis der Bedingungsblock vollständig ausgeführt ist. Wenn der Autor diese Fallstricke nicht kennt oder seinen gesamten Aufrufstapel in allen möglichen Situationen, in denen eine Funktion aufgerufen werden kann, nicht kennt, schreibt er fehlerhaften Code, und das falsche Sicherheitsgefühl, das von bereitgestellt wird, set -ewird zumindest teilweise aufgehoben Schuld.
Selbst wenn der Autor sich dieser Fallstricke voll bewusst ist, besteht die Problemumgehung darin, Code auf die gleiche Weise zu schreiben, wie man es ohne ihn schreiben würde set -e, wodurch dieser Switch weniger als nutzlos wird. Der Autor muss nicht nur den Code für die manuelle Fehlerbehandlung so schreiben, als ob er set -enicht in Kraft wäre, sondern das Vorhandensein von hat ihn set -emöglicherweise in die Irre geführt, dass er dies nicht tun muss.
Einige weitere Nachteile von set -e:
- Es fördert schlampigen Code. Fehlerbehandler werden völlig vergessen, in der Hoffnung, dass alles, was fehlgeschlagen ist, den Fehler auf eine vernünftige Weise meldet. Bei Beispielen wie
let x++oben ist dies jedoch nicht der Fall. Wenn das Skript unerwartet abstürzt, geschieht dies normalerweise im Hintergrund, was das Debuggen behindert. Wenn das Skript nicht stirbt und Sie es erwartet haben (siehe vorherigen Aufzählungspunkt), haben Sie einen subtileren und heimtückischeren Fehler in Ihren Händen.
- Es führt die Menschen in ein falsches Sicherheitsgefühl. Sehen Sie noch einmal den
ifAufzählungspunkt.
- Die Stellen, an denen die Shell endet, sind zwischen Shells oder Shell-Versionen nicht konsistent. Es ist möglich, versehentlich ein Skript zu schreiben, das sich in einer älteren Version von bash anders verhält,
set -eweil zwischen diesen Versionen Optimierungen vorgenommen wurden.
set -eist ein umstrittenes Problem, und einige Leute, die sich der Probleme bewusst sind, empfehlen, dagegen vorzugehen, während andere nur empfehlen, vorsichtig zu sein, während es aktiv ist, um die Fallstricke zu kennen. Es gibt viele Anfänger in der Shell-Skripterstellung, die set -ebei allen Skripten Abhilfe schaffen , aber im wirklichen Leben funktioniert das nicht so.
set -e ist kein Ersatz für Bildung.