Beenden Sie ein Skript bei einem Fehler

141

Ich erstelle ein Shell-Skript mit einer ifFunktion wie dieser:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables
fi

...

Ich möchte, dass die Ausführung des Skripts nach dem Anzeigen der Fehlermeldung abgeschlossen wird. Wie kann ich das machen?

Nathan Campos
quelle

Antworten:

137

Suchen Sie exit?

Dies ist der beste Bash-Guide. http://tldp.org/LDP/abs/html/

Im Zusammenhang:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables 1>&2
    exit 1 # terminate and indicate error
fi

...
Byron Whitlock
quelle
5
Wenn Sie das ABS mögen, werden Sie den BashGuide , BashFAQ und BashPitfalls lieben .
Bis auf weiteres angehalten.
Diese Bash-Links sind super! Der BashFAQ wäre besser als BashRecipes positioniert.
Pete Alvin
337

Wenn Sie set -eein Skript eingeben, wird das Skript beendet, sobald ein darin enthaltener Befehl fehlschlägt (dh sobald ein Befehl einen Status ungleich Null zurückgibt). Auf diese Weise können Sie keine eigene Nachricht schreiben, aber häufig reichen die eigenen Nachrichten des fehlgeschlagenen Befehls aus.

Der Vorteil dieses Ansatzes besteht darin, dass er automatisch abläuft: Sie laufen nicht Gefahr, zu vergessen, einen Fehlerfall zu behandeln.

Befehle, deren Status durch eine Bedingung (z. B. oder ) getestet wird if, beenden das Skript nicht (andernfalls wäre die Bedingung sinnlos). Eine Redewendung für gelegentliche Befehle, deren Fehler keine Rolle spielen . Sie können auch einen Teil des Skripts mit deaktivieren .&&||command-that-may-fail || trueset -eset +e

Gilles 'SO - hör auf böse zu sein'
quelle
3
Laut mywiki.wooledge.org/BashFAQ/105 war diese Funktion in der Vergangenheit unklar und verwickelt , um festzustellen, welche Fehlercodes von Befehlen einen automatischen Exit verursachen. Darüber hinaus "ändern sich die Regeln von einer Bash-Version zur anderen, da Bash versucht, die extrem rutschige POSIX-Definition dieser 'Funktion' zu verfolgen". Ich bin mit @Dennis Williamson und der akzeptierten Antwort von stackoverflow.com/questions/19622198/… einverstanden - benutze Trap 'error_handler' ERR. Auch wenn es eine Falle ist!
Bondolin
3
Oft reicht es aus, das -xFlag mit dem -eFlag zu verwenden, um festzustellen, wo sich Ihr Programm beim Beenden befindet. Dies bedeutet, dass der Benutzer des Skripts auch der Entwickler ist.
Alex
Schön, aber ich denke, das OP musste das Skript aus einer selbst definierten Ausnahme beenden.
27.
42

Wenn Sie in der Lage sein möchten, einen Fehler zu behandeln, anstatt ihn blind zu beenden, anstatt ihn zu verwenden set -e, verwenden Sie ein trapfür das ERRPseudosignal.

#!/bin/bash
f () {
    errorCode=$? # save the exit code as the first thing done in the trap function
    echo "error $errorCode"
    echo "the command executing at the time of the error was"
    echo "$BASH_COMMAND"
    echo "on line ${BASH_LINENO[0]}"
    # do some error handling, cleanup, logging, notification
    # $BASH_COMMAND contains the command that was being executed at the time of the trap
    # ${BASH_LINENO[0]} contains the line number in the script of that command
    # exit the script or return to try again, etc.
    exit $errorCode  # or use some other value or do return instead
}
trap f ERR
# do some stuff
false # returns 1 so it triggers the trap
# maybe do some other stuff

Andere Traps können so eingestellt werden, dass sie andere Signale verarbeiten, einschließlich der üblichen Unix-Signale sowie der anderen Bash-Pseudosignale RETURNund DEBUG.

Bis auf weiteres angehalten.
quelle
8

Hier ist der Weg, um es zu tun:

#!/bin/sh

abort()
{
    echo >&2 '
***************
*** ABORTED ***
***************
'
    echo "An error occurred. Exiting..." >&2
    exit 1
}

trap 'abort' 0

set -e

# Add your script below....
# If an error occurs, the abort() function will be called.
#----------------------------------------------------------
# ===> Your script goes here
# Done!
trap : 0

echo >&2 '
************
*** DONE *** 
************
'
Superkobra
quelle
Warum die Nachricht FERTIG an stderr?
MattBianco
1
Dies ist eine gängige Praxis, damit Sie Ihre Skriptausgabe an stdout weiterleiten können, damit ein anderer Prozess sie abrufen kann, ohne die Infomeldungen in der Mitte zu haben.
Supercobra
2
Es ist wahrscheinlich ebenso üblich, irgendetwas auf stderr als Hinweis auf Probleme zu behandeln.
MattBianco
1
In der Vergangenheit hat 'set -e' immer für mich funktioniert, aber heute Abend bin ich auf eine Situation in einem Alpine Linux Docker-Image gestoßen, in der es keine Auswirkungen hatte. Diese Lösung hat für mich funktioniert und mich wieder auf die anstehende Aufgabe gebracht. Sehr geschätzt.
Synthesizerpatel
@supercobra Übliche Praxis? Wo?
Thorbjørn Ravn Andersen
-8

exit 1ist alles, was du brauchst. Das 1ist ein Rückkehrcode, also können Sie ihn ändern, wenn Sie beispielsweise 1einen erfolgreichen Lauf und -1einen Fehler oder ähnliches bedeuten möchten .

DGH
quelle
13
Unter Unix ist der Erfolg immer 0. Dies kann bei der Verwendung von testoder &&oder hilfreich sein ||.
Mouviciel
5
Um den Kommentar von mouviciel zu erweitern: In Shell-Skripten bedeutet 0 immer Erfolg und 1 bis 255 bedeutet Misserfolg. -1 liegt außerhalb des Bereichs (und hat oft den gleichen Effekt wie 255, also ein Fehler wie 1).
Gilles 'SO - hör auf böse zu sein'
@mouviciel, @Gilles: Danke für die zusätzlichen Infos. Es ist schon eine Weile her, seit ich mich mit Bash befasst habe.
DGH
Dies ist ein schlechtes Beispiel für die Verwendung von Rückkehrcodes, andernfalls wäre es eine gute Antwort.
Brad Koch
1
Zusätzlich zur falschen Empfehlung von 1 für den Erfolg ist -1 nicht möglich (Exit-Codes sind nicht signiert).
Tripleee