Ausnahmebehandlung beim Shell-Scripting?

Antworten:

119

Es gibt nicht wirklich eine try/catchIn-Bash (ich nehme an, Sie verwenden Bash), aber Sie können mit &&oder ein ziemlich ähnliches Verhalten erzielen ||.

In diesem Beispiel möchten Sie ausführen, fallback_commandwenn dies a_command fehlschlägt (gibt einen Wert ungleich Null zurück):

a_command || fallback_command

In diesem Beispiel möchten Sie ausführen, second_commandwenn dies a_command erfolgreich ist (gibt 0 zurück):

a_command && second_command

Sie lassen sich leicht miteinander vermischt werden , indem eine Sub - Shell verwenden, beispielsweise die folgenden Befehl wird ausgeführt a_command, wenn es gelingt , es wird dann laufen other_command, aber wenn a_commandoder other_commandfehlschlägt, fallback_commandwird ausgeführt:

(a_command && other_command) || fallback_command
mdeous
quelle
14
Bonus: Wenn Sie ein "endlich" ähnliches Verhalten wünschen, verwenden Sie das No-Op (: in Bash) wie (a_command || : )folgt : Die nächste Zeile wird so ausgeführt, als wäre kein Fehler aufgetreten a_command.
BT
Genial! Hat mir viel Codierung erspart.
Mrinal
Nicht wirklich, weil die Semantik von finally darin besteht, dass es unabhängig vom Ausnahmestatus ausgeführt wird.
FP Frei
12

Die if / else-Struktur und die Exit-Codes können Ihnen dabei helfen, einige davon zu fälschen. Dies sollte in Bash oder Bourne (sh) funktionieren.

if foo ; then
else
  e=$?        # return code from if
  if [ "${e}" -eq "1"]; then
    echo "Foo returned exit code 1"
  elif [ "${e}" -gt "1"]; then
    echo "Foo returned BAD exit code ${e}"
  fi
fi
Brightlancer
quelle
1
if foo ; then elsekann if ! foo ; thentrotzdem auf +1 vereinfacht werden.
Jlliagre
2
@jiliagre Das funktioniert nicht. "! foo" invertiert $? von 0 bis 1 und! 0 bis 0.
Brightlancer
7
{
    # command which may fail and give an error 
} || {
   # command which should be run instead of the above failing      command
}
Prasad Kudalkar
quelle
5
Es wäre wahrscheinlich, betterwenn Sie demjenigen, der die Frage stellt, den Pseudocode erklären würden, den Sie veröffentlichen, und nicht nur einen Block kryptischen Codes, den sie möglicherweise nicht verstehen. Wenn ein Kind es nicht verstehen kann, ist es keine gute Antwort.
Yokai
3

Hier sind zwei einfache Bash-Funktionen, die die Ereignisbehandlung in Bash ermöglichen:

Sie können es für die grundlegende Ausnahmebehandlung wie folgt verwenden:

onFoo(){
  echo "onFoo() called width arg $1!"
}  

foo(){
  [[ -f /tmp/somefile ]] || throw EXCEPTION_FOO_OCCURED "some arg"
} 

addListener EXCEPTION_FOO_OCCURED onFoo

Die Ausnahmebehandlung mit try / catch-Blöcken wird in bash nicht unterstützt. Sie sollten jedoch versuchen, das BANGSH-Framework zu betrachten, das dies unterstützt (es ist ein bisschen wie jquery for bash).

Allerdings ist Exceptionhandling ohne Kaskadierung try / catch-Blöcke ähnlich wie Ereignisbehandlung , die ist in fast möglich jede Sprache mit Array-Unterstützung.

Wenn Sie Ihren Code schön und ordentlich halten möchten (ohne if / else-Ausführlichkeit), würde ich die Verwendung von Ereignissen empfehlen.

Der von MatToufoutu empfohlene Vorschlag (mit || und &&) wird für Funktionen nicht empfohlen, für einfache Befehle jedoch in Ordnung . (Siehe BashPitfalls zu den Risiken)

coderofsalvation
quelle
0

Verwenden Sie Folgendes, um Fehler richtig zu behandeln, wobei error_exit eine Funktion ist, die ein Argument akzeptiert. Wenn das Argument nicht übergeben wird, wird mit LineNo ein unbekannter Fehler ausgegeben, bei dem tatsächlich ein Fehler auftritt. Bitte experimentieren Sie, bevor Sie es tatsächlich für die Produktion verwenden -

#!/bin/bash

PROGNAME=$(basename $0)

error_exit()

{

    echo "${PROGNAME}: ${1:-"Unknown Error"}" 1>&2
    exit 1
}

echo "Example of error with line number and message"
error_exit "$LINENO: An error has occurred."
Abhishek Jain
quelle