Dies ist eine alte Frage, aber keiner der Antworten hier diskutiert die Verwendung von set -e
aka set -o errexit
in Debian-Paket-Handling-Skripten. Die Verwendung dieser Option ist in diesen Skripten obligatorisch gemäß der Debian-Richtlinie; offensichtlich soll jede Möglichkeit eines unbehandelten Fehlerzustands vermieden werden.
Was dies in der Praxis bedeutet, ist, dass Sie unter welchen Bedingungen die von Ihnen ausgeführten Befehle einen Fehler zurückgeben können, verstehen müssen und jeden dieser Fehler explizit behandeln müssen.
Gemeinsame Fallstricke sind z. B. diff
(gibt einen Fehler zurück, wenn es einen Unterschied gibt) und grep
(gibt einen Fehler zurück, wenn es keine Übereinstimmung gibt). Sie können die Fehler mit expliziter Behandlung vermeiden:
diff das dies ||
echo "$0: Es gab einen Unterschied" >&2
grep katze essen ||
echo "$0: keine Katze im Essen" >&2
(Beachten Sie auch, wie wir darauf achten, den Namen des aktuellen Skripts in der Nachricht zu erwähnen und Diagnosemeldungen an den Standardfehlerausgang anstelle des Standardausgangs zu schreiben.)
Wenn keine explizite Bearbeitung wirklich notwendig oder nützlich ist, tun Sie explizit nichts:
diff das dies || true
grep katze essen || :
(Die Verwendung des No-Op-Befehls :
der Shell ist etwas obskur, aber ziemlich häufig gesehen.)
Nur zur Wiederholung,
etwas || anderer
ist eine Abkürzung für
if something; then
: nichts
else
other
fi
d. h. wir sagen ausdrücklich, dass other
ausgeführt werden soll, wenn und nur wenn something
fehlschlägt. Die ausführliche if
-Anweisung (und andere Shell-Flusssteuerungsanweisungen wie while
, until
) ist auch ein gültiger Weg, um einen Fehler zu behandeln (tatsächlich könnten shell-Skripte mit set -e
keine Flusssteuerungsanweisungen enthalten, wenn dies nicht der Fall wäre!)
Und auch nur zur Verdeutlichung, in Abwesenheit eines Handlers wie diesem würde set -e
das gesamte Skript sofort mit einem Fehler fehlschlagen lassen, wenn diff
einen Unterschied fände oder wenn grep
keine Übereinstimmung fände.
Andererseits produzieren einige Befehle keinen Fehlerausgangsstatus, wenn Sie möchten, dass sie dies tun. Häufig problematische Befehle sind z. B. find
(der Ausgangsstatus spiegelt nicht wider, ob tatsächlich Dateien gefunden wurden) und sed
(der Ausgangsstatus verrät nicht, ob das Skript Eingaben erhalten hat oder tatsächlich erfolgreich Befehle ausgeführt hat). Eine einfache Absicherung in einigen Szenarien ist, an einen Befehl zu pipen, der schreit, wenn keine Ausgabe vorhanden ist:
find dinge | grep .
sed -e 's/o/ich/' sachen | grep ^
Es sollte angemerkt werden, dass der Ausgangsstatus einer Pipeline der Ausgangsstatus des letzten Befehls in dieser Pipeline ist. Daher maskieren die obigen Befehle tatsächlich vollständig den Status von find
und sed
grep schließlich erfolgreich war.
(Bash hat natürlich set -o pipefail
; aber Debian-Paket-Skripte können keine Bash-Funktionen verwenden. Die Richtlinie schreibt eindeutig die Verwendung von POSIX sh
für diese Skripte vor, obwohl dies nicht immer der Fall war.)
In vielen Situationen ist dies etwas, worauf man bei defensiver Programmierung gesondert achten muss. Manchmal muss man z. B. durch eine temporäre Datei gehen, damit man sehen kann, ob der Befehl, der diese Ausgabe erzeugt hat, erfolgreich beendet wurde, auch wenn Idiom und Bequemlichkeit Sie eigentlich dazu bringen würden, eine Shell-Pipeline zu verwenden.