Dies ist eine alte Frage, aber keine der Antworten hier beschreibt die Verwendung von set -e
aka set -o errexit
in Debian-Paketsammlungsskripten. Die Verwendung dieser Option ist in diesen Skripten gemäß der Debian-Richtlinie obligatorisch . Die Absicht ist offenbar, die Möglichkeit eines unbehandelten Fehlerzustands zu vermeiden.
In der Praxis bedeutet dies, dass Sie verstehen müssen, unter welchen Bedingungen die von Ihnen ausgeführten Befehle einen Fehler zurückgeben können, und jeden dieser Fehler explizit behandeln müssen.
Häufige Fallstricke sind z. B. diff
(gibt einen Fehler zurück, wenn es einen Unterschied gibt) und grep
(gibt einen Fehler zurück, wenn keine Übereinstimmung vorliegt). Sie können die Fehler durch explizite Behandlung vermeiden:
diff this that ||
echo "$0: there was a difference" >&2
grep cat food ||
echo "$0: no cat in the food" >&2
(Beachten Sie auch, wie wir darauf achten, den Namen des aktuellen Skripts in die Nachricht aufzunehmen und Diagnosemeldungen anstelle der Standardausgabe in den Standardfehler zu schreiben.)
Wenn keine explizite Behandlung wirklich notwendig oder nützlich ist, tun Sie explizit nichts:
diff this that || true
grep cat food || :
(Die Verwendung des :
No-Op-Befehls der Shell ist etwas unklar, wird aber häufig verwendet.)
Nur um es noch einmal zu wiederholen,
something || other
ist eine Abkürzung für
if something; then
: nothing
else
other
fi
dh wir sagen ausdrücklich, other
sollte ausgeführt werden, wenn und nur wenn something
fehlschlägt. Die Langschrift if
(und andere Shell - Flusskontrolle Aussagen wie while
, until
) ist auch ein gültiger Weg , um einen Fehler zu behandeln (in der Tat, wenn es mit nicht, Shell - Skripte set -e
nie Flusskontrolle Aussagen enthalten könnte!)
Und nur um genau zu sein, würde in Abwesenheit eines solchen set -e
Handlers das gesamte Skript sofort mit einem Fehler fehlschlagen, wenn diff
ein Unterschied festgestellt wird oder wenn grep
keine Übereinstimmung gefunden wird.
Andererseits erzeugen einige Befehle keinen Fehler-Exit-Status, wenn Sie dies wünschen. Häufig problematische Befehle sind find
(der Exit-Status gibt nicht an, ob tatsächlich Dateien gefunden wurden) und sed
(Der Exit-Status zeigt nicht an, ob das Skript Eingaben empfangen oder tatsächlich erfolgreich Befehle ausgeführt hat). In einigen Szenarien besteht eine einfache Wache darin, zu einem Befehl zu leiten, der schreit, wenn keine Ausgabe erfolgt:
find things | grep .
sed -e 's/o/me/' stuff | grep ^
Es ist zu beachten, dass der Exit-Status einer Pipeline der Exit-Status des letzten Befehls in dieser Pipeline ist. Die obigen Befehle maskieren also den Status von find
und vollständig sed
und sagen Ihnen nur, ob dies grep
letztendlich erfolgreich war.
(Bash hat es natürlich getan set -o pipefail
; Debian-Paketskripte können jedoch keine Bash-Funktionen verwenden. Die Richtlinie schreibt die Verwendung von POSIX sh
für diese Skripte fest vor, obwohl dies nicht immer der Fall war.)
In vielen Situationen ist dies beim defensiven Codieren separat zu beachten. Manchmal müssen Sie z. B. eine temporäre Datei durchgehen, um zu sehen, ob der Befehl, der diese Ausgabe erzeugt hat, erfolgreich beendet wurde, selbst wenn Sie sonst aufgrund der Redewendung und Zweckmäßigkeit angewiesen werden, eine Shell-Pipeline zu verwenden.