Ich habe einige Bash-Skripte eingerichtet, die hauptsächlich verwenden
#!/bin/bash
aber ich stoße regelmäßig auf welche, die aussehen wie
#!/bin/bash -e
#!/bin/bash -x
#!/bin/bash -ex
und so weiter.
Kann jemand die Bedeutung und Vorteile dieser Shebang-Optionen erklären und ob sie auch für andere Shebangs gelten?
Antwort1
Wenn ein Skript /path/to/foo
mit beginnt #!/bin/bash
, ist die Ausführung /path/to/foo arg1 arg2
gleichbedeutend mit der Ausführung von /bin/bash /path/too/foo arg1 arg2
. Wenn die Shebang-Zeile lautet #!/bin/bash -ex
, ist sie gleichbedeutend mit der Ausführung von /bin/bash -ex /path/too/foo arg1 arg2
. Diese Funktion wird vom Kernel verwaltet.
Beachten Sie, dass Sie portabel nur ein Argument in der Shebang-Zeile haben können: Einige Unix-Systeme (wie etwa Linux) akzeptieren nur ein Argument, was #!/bin/bash -e -x
dazu führen würde, dass Bash das einzelne fünfstellige Argument -e -x
(ein Syntaxfehler) statt zwei Argumente -e
und erhält -x
.
Für die Bourne-Shell sh
und abgeleitete Shells wie POSIX sh, bash, ksh und zsh:
-e
bedeutet, dass das Skript sofort beendet wird, wenn ein Befehl fehlschlägt (was durch die Rückgabe eines Status ungleich Null angezeigt wird).-x
bewirkt, dass die Shell einen Ausführungs-Trace druckt.
Andere Programme verstehen diese Optionen möglicherweise, haben aber eine andere Bedeutung.
Antwort2
Es handelt sich um Optionen, die übergeben werden , um weitere Informationen bash
anzuzeigen help set
. In diesem Fall:
-x Print commands and their arguments as they are executed.
-e Exit immediately if a command exits with a non-zero status.
Antwort3
Ich möchte nur eine noch bessere – also portablere – Alternative erwähnen:
#!/usr/bin/env bash
Das obige Beispiel verwendet, env
um die bash
ausführbare Datei zu finden, die nicht immer bei ist /bin/bash
. Alte #!/bin/bash
Skripte funktionieren nicht aufNixOS, Zum Beispiel.
Wenn Sie env
wie oben gezeigt verwenden, können Sie kein Argument wie -e
to angeben bash
(soweit ich weiß). Aber Sie können stattdessen Folgendes tun:
#!/usr/bin/env bash
set -e
Antwort4
Das Starten eines Skripts mit oder das entsprechende Ausführen von hat dieselbe Wirkung wie das Einfügen innerhalb des Skripts direkt nach seiner Zeile.#! /path/to/bash -option
bash -option /path/to/script
set -option
#!
set -x
dient im Wesentlichen nur zum Debuggen. Normalerweise möchten Sie es nicht eingeschaltet lassen.
Die Wirkung set -e
ist viel komplizierter als es die Anleitung vermuten lässt. Die genauere Beschreibung lautet etwa:
set -e
Wenn nach dem Aufruf vonungetestetDer Befehl wird mit einem Status ungleich Null beendet. Dadurch wird die Shell mit diesem Beendigungsstatus beendet.
ich sageetwas genauerweil es immer noch ziemlich vage ist: die Liste der Situationen, in denen der Befehl berücksichtigt wirdgeprüftist geheimnisvoll und schwer vorherzusagen. Die genauen Regeln unterscheiden sich zwischen Shells und ändern sich sogar zwischen Versionen derselben Shell.
set -e
tutnichtBeenden Sie Bash, wenn der Exit-Status eines beliebigen Befehls ungleich Null ist:
- zwischen
if
/elif
undthen
; oder - zwischen
while
/until
unddo
; oder - folgendes
!
; oder - gefolgt von
||
„oder“&&
oder „oder“&
(wobei&
das entsprechendewait
„oder“fg
fehlschlagen kann); oder - gefolgt von
|
, es sei denn,set -o pipefail
es ist wirksam; oder - innerhalb
$( ... )
, wenn es als Teil eines Befehls verwendet wird (keine bloßen Zuweisungen und/oder Umleitungen, was bedeutet, dass esfoo=$( bar )
fehlschlägt, wennbar
es fehlschlägt, aberlocal foo=$( bar )
nicht); oder - innerhalb eines zusammengesetzten Befehls, wenn die oben genannten Punkte zutreffen; oder
- Innerhalb einer Shell-Funktion, die von überall aufgerufen wird, gilt das oben Gesagte.
Die Auswirkungen auf zusammengesetzte Befehle und Shell-Funktionen sind rekursiv.
Da die Shell selbst mit einem Status ungleich Null beendet wird, kann sich der Effekt aus einer Unter-Shell ausbreiten.
Die !
Ausnahme gilt auch dann, wenn der invertierte Exit-Status ignoriert wird.
Umgekehrt set -e
können Auslöserjeder andereStatus ungleich Null, unabhängig davon, ob er „fehlgeschlagen“ oder einfach „falsch“ bedeutet. Beispielsweise ((x++))
hat der Exit-Status ungleich Null „fehlgeschlagen“, wenn x
er anfänglich 0 ist.
Weil es so ein Durcheinander ist, gibt es eine Denkschule, die besagt, dass es set -e
vermieden werden sollte, und stattdessen alle Befehle explizit überprüft werden sollten.
Oder wenn Sie dennoch verwenden möchten set -e
, denken Sie daran, !
vor alle ((arithmetic))
Gruppen zu schreiben.