Ich habe ein Bash-Shell-Skript, das eine Reihe von Befehlen aufruft. Ich möchte, dass das Shell-Skript automatisch mit einem Rückgabewert von 1 beendet wird, wenn einer der Befehle einen Wert ungleich Null zurückgibt.
Ist dies möglich, ohne das Ergebnis jedes Befehls explizit zu überprüfen?
z.B
dosomething1
if [[ $? -ne 0 ]]; then
exit 1
fi
dosomething2
if [[ $? -ne 0 ]]; then
exit 1
fi
set -e
auchset -u
(oderset -eu
).-u
Beendet das idiotische Verhalten, das Fehler versteckt, dass Sie auf jede nicht vorhandene Variable zugreifen können und einen leeren Wert ohne Diagnose erstellen lassen.Antworten:
Fügen Sie dies am Anfang des Skripts hinzu:
Dies führt dazu, dass die Shell sofort beendet wird, wenn ein einfacher Befehl mit einem Exit-Wert ungleich Null beendet wird. Ein einfacher Befehl ist ein Befehl, der nicht Teil eines if, while oder bis zum Test oder Teil eines && oder || ist Liste.
Siehe die bash (1) man - Seite auf dem „set“ internen Befehl für weitere Details.
Ich persönlich starte fast alle Shell-Skripte mit "set -e". Es ist wirklich ärgerlich, wenn ein Skript hartnäckig fortgesetzt wird, wenn etwas in der Mitte fehlschlägt und die Annahmen für den Rest des Skripts verletzt.
quelle
bash script.sh
.set -e; tf() { false; }; tf; echo 'still here'
. Auch ohneset -e
im Körper vontf()
wird die Ausführung abgebrochen. Vielleicht wollten Sie damit sagen, dass diesset -e
nicht von Unterschalen geerbt wird , was wahr ist.So ergänzen Sie die akzeptierte Antwort:
Denken Sie daran, dass dies
set -e
manchmal nicht ausreicht, insbesondere wenn Sie Rohre haben.Angenommen, Sie haben dieses Skript
... was wie erwartet funktioniert: Ein Fehler in
configure
bricht die Ausführung ab.Morgen nehmen Sie eine scheinbar triviale Änderung vor:
... und jetzt funktioniert es nicht. Dies wird hier erklärt und es wird eine Problemumgehung (nur Bash) bereitgestellt:
quelle
pipefail
, mitmachen zu müssenset -o
!Die if-Anweisungen in Ihrem Beispiel sind nicht erforderlich. Mach es einfach so:
Wenn Sie den Rat von Ville Laurikari befolgen und
set -e
für einige Befehle verwenden, müssen Sie möglicherweise Folgendes verwenden:Dadurch
|| true
erhält die Befehlspipeline einentrue
Rückgabewert, auch wenn der Befehl fehlschlägt, sodass die-e
Option das Skript nicht beendet.quelle
set -e
ist nicht bash-zentriert - es wird sogar von der ursprünglichen Bourne Shell unterstützt.Wenn Sie beim Beenden eine Bereinigung durchführen müssen, können Sie auch 'trap' mit dem Pseudosignal ERR verwenden. Dies funktioniert genauso wie das Einfangen von INT oder einem anderen Signal. bash löst ERR aus, wenn ein Befehl mit einem Wert ungleich Null beendet wird:
Oder wenn Sie "set -e" verwenden, können Sie EXIT abfangen. Ihre Trap wird dann ausgeführt, wenn das Skript aus irgendeinem Grund beendet wird, einschließlich eines normalen Endes, Interrupts, eines durch die Option -e verursachten Exits usw.
quelle
Die
$?
Variable wird selten benötigt. Das Pseudo-Idiomcommand; if [ $? -eq 0 ]; then X; fi
sollte immer als geschrieben werdenif command; then X; fi
.In den Fällen, in denen dies
$?
erforderlich ist, muss es mit mehreren Werten verglichen werden:oder wenn
$?
es wiederverwendet oder anderweitig manipuliert werden muss:quelle
Führen Sie es mit
-e
oderset -e
oben aus.Schauen Sie sich auch an
set -u
.quelle
help set
:-u
behandelt Verweis auf nicht definierter Variablen als Fehler.set -u
oderset -e
nicht beides? @lumpynoseEin Ausdruck wie
beendet die Verarbeitung, wenn einer der Befehle mit einem Wert ungleich Null zurückgegeben wird. Der folgende Befehl gibt beispielsweise niemals "erledigt" aus:
quelle
sollte ausreichen.
quelle
Wirf einfach eine andere als Referenz ein, da es eine zusätzliche Frage zu Mark Edgars Input gab. Hier ist ein zusätzliches Beispiel und berührt das Thema insgesamt:
Das ist das gleiche
cmd || exit errcode
wie jemand gezeigt hat.z.B. Ich möchte sicherstellen, dass eine Partition nicht gemountet ist, wenn sie gemountet ist:
quelle
[[
cmd`]] `ist nicht dasselbe. Es ist falsch, wenn die Ausgabe des Befehls leer und ansonsten wahr ist, unabhängig vom Beendigungsstatus des Befehls.