890 Stimmen

Wie kann ich in einem Bash-Skript das gesamte Skript beenden, wenn eine bestimmte Bedingung eintritt?

Ich schreibe ein Skript in Bash, um einen Code zu testen. Es scheint jedoch dumm, die Tests auszuführen, wenn die Kompilierung des Codes in erster Linie fehlschlägt, in diesem Fall werde ich einfach die Tests abbrechen.

Gibt es eine Möglichkeit, dies zu tun, ohne das gesamte Skript in eine while-Schleife zu packen und Pausen zu verwenden? Etwas wie ein mahnen mahnen mahnen gehen?

1039voto

Michael Foukarakis Punkte 37819

Versuchen Sie diese Aussage:

exit 1

Ersetzen Sie 1 mit entsprechenden Fehlercodes. Siehe auch Exit Codes mit besonderen Bedeutungen .

781voto

Shizzmo Punkte 15411

Utilice setzen -e

#!/bin/bash

set -e

/bin/command-that-fails
/bin/command-that-fails2

Das Skript wird nach der ersten fehlgeschlagenen Zeile beendet (gibt einen Exit-Code ungleich Null zurück). In diesem Fall, befehl-der-misslingt2 wird nicht ausgeführt.

Wenn Sie den Rückgabestatus jedes einzelnen Befehls überprüfen würden, würde Ihr Skript wie folgt aussehen:

#!/bin/bash

# I'm assuming you're using make

cd /project-dir
make
if [[ $? -ne 0 ]] ; then
    exit 1
fi

cd /project-dir2
make
if [[ $? -ne 0 ]] ; then
    exit 1
fi

Mit setzen -e würde es so aussehen:

#!/bin/bash

set -e

cd /project-dir
make

cd /project-dir2
make

Jeder Befehl, der fehlschlägt, führt dazu, dass das gesamte Skript fehlschlägt und einen Exit-Status zurückgibt, den Sie überprüfen können mit $? . Wenn Ihr Skript sehr lang ist oder Sie eine Menge Zeug bauen, wird es ziemlich hässlich, wenn Sie überall Rückgabestatusprüfungen hinzufügen.

297voto

c.gutierrez Punkte 4392

Ein SysOps-Mitarbeiter hat mir einmal die Drei-Finger-Krallen-Technik beigebracht:

yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "cannot $*"; }

Diese Funktionen sind für das *NIX-Betriebssystem und die Shell-Variante geeignet. Setzen Sie sie an den Anfang Ihres Skripts (Bash oder anders), try() Ihre Aussage und Ihren Code weiter.

Erläuterung

(basierend auf fliegende Schafe Kommentar).

  • yell : Druckt den Skriptnamen und alle Argumente an stderr :
    • $0 ist der Pfad zum Skript ;
    • $* sind alle Argumente.
    • >&2 bedeutet > stdout auf & pipe umleiten 2 . Rohr 1 wäre stdout selbst.
  • die tut dasselbe wie yell , sondern verlässt ihn mit einer Nicht-0-Ausgangsstatus was "durchfallen" bedeutet.
  • try verwendet die || (boolescher OR ), die die rechte Seite nur dann auswertet, wenn die linke Seite fehlgeschlagen ist.

43voto

kavadias Punkte 1007

Wenn Sie das Skript mit source können Sie verwenden return <x> donde <x> ist der Beendigungsstatus des Skripts (verwenden Sie einen Wert ungleich Null für error oder false). Wenn Sie jedoch ein ausführbares Skript aufrufen (d.h. direkt mit dessen Dateinamen), führt die return-Anweisung zu einer Beschwerde (Fehlermeldung "return: can only `return' from a function or sourced script").

Si exit <x> wird stattdessen verwendet, wenn das Skript mit source wird die Shell, die das Skript gestartet hat, beendet, aber ein ausführbares Skript wird wie erwartet einfach beendet.

Um beide Fälle in demselben Skript zu behandeln, können Sie

return <x> 2> /dev/null || exit <x>

Damit wird jeder beliebige Aufruf bearbeitet, der geeignet ist. Dies setzt voraus, dass Sie diese Anweisung auf der obersten Ebene des Skripts verwenden. Ich würde davon abraten, das Skript direkt aus einer Funktion heraus zu beenden.

Anmerkung: <x> soll nur eine Zahl sein.

15voto

Joseph Sheedy Punkte 5876

Ich füge oft eine Funktion namens run() ein, um Fehler zu behandeln. Jeder Aufruf, den ich machen möchte, wird an diese Funktion übergeben, so dass das gesamte Skript bei einem Fehler beendet wird. Der Vorteil gegenüber der Lösung mit set -e ist, dass das Skript nicht stillschweigend beendet wird, wenn eine Zeile fehlschlägt, und dass es Ihnen mitteilen kann, wo das Problem liegt. Im folgenden Beispiel wird die 3. Zeile nicht ausgeführt, weil das Skript beim Aufruf von false beendet wird.

function run() {
  cmd_output=$(eval $1)
  return_value=$?
  if [ $return_value != 0 ]; then
    echo "Command $1 failed"
    exit -1
  else
    echo "output: $cmd_output"
    echo "Command succeeded."
  fi
  return $return_value
}
run "date"
run "false"
run "date"

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X