Ich habe ein Bash Shell-Skript, das eine Reihe von Befehlen aufruft. Ich möchte, dass das Shell-Skript automatisch mit dem Rückgabewert 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
Fügen Sie dies am Anfang des Skripts hinzu:
set -e
Dadurch wird die Shell sofort beendet, wenn ein einfacher Befehl mit einem Exit-Wert ungleich Null beendet wird. Ein einfacher Befehl ist ein beliebiger Befehl, der nicht Teil eines if, while oder until-Tests oder Teil eines && oder || ist Liste.
Weitere Informationen finden Sie in der Manpage bash (1) zum internen Befehl "set".
Ich persönlich starte fast alle Shell-Skripte mit "set -e". Es ist wirklich ärgerlich, wenn ein Skript hartnäckig weiterarbeitet, wenn etwas in der Mitte versagt und die Annahmen für den Rest des Skripts verletzt.
So fügen Sie der akzeptierten Antwort hinzu:
Bedenke, dass set -e
reicht manchmal nicht aus, besonders wenn Sie Pfeifen haben.
Angenommen, Sie haben dieses Skript
#!/bin/bash
set -e
./configure > configure.log
make
... was wie erwartet funktioniert: Ein Fehler in configure
bricht die Ausführung ab.
Morgen nehmen Sie eine scheinbar triviale Änderung vor:
#!/bin/bash
set -e
./configure | tee configure.log
make
... und jetzt klappt es nicht. Dies wird erklärt hier , und es wird eine Problemumgehung (nur Bash) bereitgestellt:
#!/bin/bash set -e set -o pipefail ./ configure | tee configure.log make
Die if-Anweisungen in Ihrem Beispiel sind nicht erforderlich. Mach es einfach so:
dosomething1 || exit 1
Wenn Sie den Rat von Ville Laurikari befolgen und set -e
Verwenden, müssen Sie für einige Befehle möglicherweise Folgendes eingeben:
dosomething || true
Mit || true
Erhält die Befehlspipeline einen true
-Rückgabewert, auch wenn der Befehl fehlschlägt, sodass die Option -e
Das Skript nicht beendet.
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 Abfangen von INT oder anderen Signalen. bash löst ERR aus, wenn ein Befehl mit einem Wert ungleich Null beendet wird:
# Create the trap with
# trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah
Oder, besonders 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.
Führen Sie es mit -e
oder set -e
oben.
Siehe auch set -u
.
Das $?
Variable wird selten benötigt. Das Pseudo-Idiom command; if [ $? -eq 0 ]; then X; fi
sollte immer geschrieben werden als if command; then X; fi
.
Die Fälle, in denen $?
wird benötigt, wenn es gegen mehrere Werte geprüft werden soll:
command
case $? in
(0) X;;
(1) Y;;
(2) Z;;
esac
oder wann $?
muss wiederverwendet oder anderweitig manipuliert werden:
if command; then
echo "command successful" >&2
else
ret=$?
echo "command failed with exit code $ret" >&2
exit $ret
fi
#!/bin/bash -e
sollte ausreichen.
Ein Ausdruck wie
dosomething1 && dosomething2 && dosomething3
beendet die Verarbeitung, wenn einer der Befehle einen Wert ungleich Null zurückgibt. Der folgende Befehl gibt beispielsweise niemals "erledigt" aus:
cat nosuchfile && echo "done"
echo $?
1