Ich habe als Bash-Shell-Skript mit Header #!/bin/bash -e
.
Wenn ich das Skript ausführe, wird es unterbrochen, nachdem der grep
Befehl ausgeführt wurde. Wenn ich jedoch den Parameter entferne -e
, kann das Skript normal ausgeführt werden. Was bedeutet Parameter -e
?
-e
Option für Bash . Was passiert also wirklich in diesem Fall? :(-e
Option für Bash: serverfault.com/questions/391255/… .Antworten:
Die
-e
Option bedeutet "Wenn eine Pipeline jemals mit einem Exit-Status ungleich Null ('Fehler') endet, beenden Sie das Skript sofort". Dagrep
der Exit-Status zurückgegeben wird,1
wenn keine Übereinstimmung gefunden wird, kann-e
das Skript beendet werden, auch wenn kein wirklicher "Fehler" aufgetreten ist.Wenn Sie die
-e
Option beibehalten möchten , aber auch einengrep
Befehl haben möchten, der möglicherweise keine Übereinstimmungen findet, können Sie ihn|| :
an dengrep
Befehl anhängen . Dies bedeutet "oder, wenn dergrep
Befehl einen Exit-Status ungleich Null zurückgibt, run:
(was nichts bewirkt)"; Der Nettoeffekt besteht also darin,-e
dengrep
Befehl zu deaktivieren . Damit:Bearbeitet hinzufügen: Der obigen Ansatz verwirft jeden Fehler: Wenn
grep
Rückkehr ,1
weil es keine Einträge gefunden, die ignoriert wird , aber auch , wenngrep
Rückkehr ,2
weil es ein Fehler, die ignoriert wird , und wenngrep
nicht in dem Weg (so Bash zurückkehrt127
), dass die ignoriert - und so weiter. Daher ist:
es wahrscheinlich besser, einen Befehl zu verwenden, der den Ergebniscode überprüft und den Fehler erneut ausgibt, wenn es sich um etwas anderes handelt1
. Zum Beispiel:Dies zerstört jedoch den Exit-Status. Wenn ein fehlgeschlagener Befehl ein Bash-Skript mit beendet
-e
, gibt das Skript normalerweise den Exit-Status des Befehls zurück. Im obigen Beispiel wird das Skript jedoch nur zurückgegeben1
. Wenn (und nur wenn) uns das interessiert, können wir es beheben, indem wir so etwas schreiben:grep PATTERN FILE || exit_code=$? if (( exit_code > 1 )) ; then exit $exit_code fi
(erste Zeile c / o dsummersls Kommentar).
An dieser Stelle ist es wahrscheinlich am besten, eine Shell-Funktion zu erstellen, um dies für uns zu erledigen:
function grep_no_match_ok () { local exit_code grep "$@" || exit_code=$? return $(( exit_code == 1 ? 0 : exit_code )) }
(Beachten Sie die Verwendung von
return
anstatt vonexit
; wir lassen-e
das Verlassen gegebenenfalls behandeln); Auf diese Weise können wir einfach schreiben:grep_no_match_ok PATTERN FILE # won't kill script if no matches are found
Da wir diese Funktion höchstwahrscheinlich für alle Vorkommen
grep
in diesem Skript verwenden möchten , können wir die Funktion tatsächlich nur benennengrep
:function grep () { local exit_code command grep "$@" || exit_code=$? return $(( exit_code == 1 ? 0 : exit_code )) } grep PATTERN FILE # won't kill script if no matches are found
(Beachten Sie die Verwendung von
command
, um die Shell-Funktion in ihrem eigenen Körper zu umgehen: Wir möchten, dass die Funktion das reguläre Programmgrep
aufruft, anstatt unendlich zu rekursieren).quelle
grep XXX FILE || exitcode=$?
. Super praktisch!Aus dem feinen Handbuch :
Und wenn wir uns dann ansehen, was
set
zu sagen ist:Wenn Sie also sagen
bash -e
, wenn ein Befehl im Skript fehlschlägt (dh einen Status ungleich Null zurückgibt), schlägt das gesamte Skript sofort fehl. Sie gebengrep
also einen Wert ungleich Null zurück, da dieser nicht übereinstimmt und das gesamte Skript heruntergefahren wird, wenn Sie-e
beim Ausführen von bash angeben .quelle