it-swarm.com.de

Wie kann ich das Programm beenden, wenn ein Befehl fehlgeschlagen ist?

Ich bin ein Noob in Shell-Scripting. Ich möchte eine Nachricht drucken und mein Skript beenden, wenn ein Befehl fehlschlägt. Ich habe es versucht:

my_command && (echo 'my_command failed; exit)

aber es funktioniert nicht. Es werden weiterhin die Anweisungen ausgeführt, die dieser Zeile im Skript folgen. Ich benutze Ubuntu und bash.

183
user459246

Versuchen:

my_command || { echo 'my_command failed' ; exit 1; }

Vier Änderungen:

  • Veränderung && bis ||
  • Verwenden { } anstelle von ( )
  • Vorstellen ; nach exit und
  • leerzeichen nach { und davor }

Da Sie die Nachricht drucken und erst beenden möchten, wenn der Befehl fehlschlägt (wird mit einem Wert ungleich Null beendet), benötigen Sie ein || kein &&.

cmd1 && cmd2

werde rennen cmd2 wann cmd1 erfolgreich (Exit-Wert 0). Wohingegen

cmd1 || cmd2

werde rennen cmd2 wann cmd1 schlägt fehl (Ausgangswert ungleich Null).

Mit ( ) bewirkt, dass der darin enthaltene Befehl in einer Sub-Shell ausgeführt und ein exit von aufgerufen wird Dort verlassen Sie die Sub-Shell und nicht Ihre ursprüngliche Shell. Daher wird die Ausführung in Ihrer ursprünglichen Shell fortgesetzt.

Um dies zu überwinden, benutze { }

Die letzten beiden Änderungen sind für die Bash erforderlich.

346
codaddict

Die anderen Antworten haben die direkte Frage gut abgedeckt, aber Sie könnten auch daran interessiert sein, set -e Zu verwenden. Damit führt jeder fehlgeschlagene Befehl (außerhalb bestimmter Kontexte wie if tests) zum Abbruch des Skripts. Für bestimmte Skripte ist es sehr nützlich.

118
Daenyth

Wenn Sie dieses Verhalten für alle Befehle in Ihrem Skript wünschen, fügen Sie einfach hinzu

  set -e 
  set -o pipefail

am Anfang des Skripts. Dieses Optionspaar weist den Bash-Interpreter an, zu beenden, wenn ein Befehl mit einem Exit-Code ungleich Null zurückgegeben wird.

Auf diese Weise können Sie jedoch keine Beendigungsnachricht drucken.

58
damienfrancois

Beachten Sie auch, dass der Beendigungsstatus jedes Befehls in der Shell-Variablen $? Gespeichert ist, die Sie unmittelbar nach dem Ausführen des Befehls überprüfen können. Ein Status ungleich Null zeigt einen Fehler an:

my_command
if [ $? -eq 0 ]
then
    echo "it worked"
else
    echo "it failed"
fi
57
Alex Howansky

Ich habe die folgende Redewendung gehackt:

echo "Generating from IDL..."
idlj -fclient -td Java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Compiling classes..."
javac *Java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Done."

Stellen Sie jedem Befehl ein informatives Echo voran und folgen Sie jedem Befehl mit demselben
if [ $? -ne 0 ];... Linie. (Natürlich können Sie diese Fehlermeldung bearbeiten, wenn Sie möchten.)

13

Unter der Voraussetzung my_command ist kanonisch angelegt, ie liefert bei Erfolg 0, dann && ist genau das Gegenteil von dem, was Sie wollen. Sie wollen ||.

Beachten Sie auch, dass ( scheint mir nicht richtig zu sein, aber ich kann nicht versuchen, wo ich bin. Sag mir.

my_command || {
    echo 'my_command failed' ;
    exit 1; 
}
10
Benoit

Sie können auch Folgendes verwenden, um den Fehlerstatus beim Beenden beizubehalten und eine lesbare Datei mit einem Befehl pro Zeile zu erstellen:

my_command1 || exit $?
my_command2 || exit $?

Hierdurch wird jedoch keine zusätzliche Fehlermeldung ausgegeben. In einigen Fällen wird der Fehler jedoch trotzdem durch den fehlgeschlagenen Befehl ausgegeben.

4
alexpirine

Die trap -Shell ermöglicht das Abfangen von Signalen und anderen nützlichen Bedingungen, einschließlich einer fehlgeschlagenen Befehlsausführung (d. H. Ein Rückgabestatus ungleich Null). Wenn Sie also nicht den Rückgabestatus jedes einzelnen Befehls explizit testen möchten, können Sie trap "your Shell code" ERR und der Shell-Code werden immer dann ausgeführt, wenn ein Befehl einen Nicht-Null-Status zurückgibt. Beispielsweise:

trap "echo script failed; exit 1" ERR

Beachten Sie, dass Pipelines wie in anderen Fällen, in denen fehlgeschlagene Befehle abgerufen werden, eine besondere Behandlung benötigen. die oben genannten werden nicht fangen false | true.

3
kozel

Die folgenden Funktionen geben nur dann Fehler aus, wenn ein Befehl fehlschlägt:

silently () {
    label="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${label}: ${error}" >&2
        exit 1
    fi
}