Angenommen, ich habe eine Bash-Funktion wie diese:
gmx(){ echo "foo"; }
wird diese Funktion implizit ausgeführt Geben Sie den Exit-Wert des Befehls echo
zurück oder ist die Verwendung von return erforderlich?
gmx(){ echo "foo"; return $? }
Ich gehe davon aus, dass dies der Fall ist bash funktioniert, der Exit-Status des letzten Befehls der bash-Funktion wird „zurückgegeben“, ist aber nicht 100% sicher.
Antwort
return
gibt eine explizite Rückgabe von einer Shell-Funktion oder einem“ Punktskript „(einem Quellenskript) aus. Wenn return
nicht ausgeführt wird, erfolgt eine implizite Rückgabe am Ende der Shell-Funktion oder des Punktskripts.
Wenn return
wird ohne Parameter ausgeführt. Dies entspricht der Rückgabe des Exit-Status des zuletzt ausgeführten Befehls.
So funktioniert return
in allen POSIX-Versionen Shells.
Zum Beispiel entspricht
gmx () { echo "foo" return "$?" }
daher
gmx () { echo "foo" return }
entspricht
gmx () { echo "foo" }
Im Allgemeinen ist es sehr selten, dass Sie $?
überhaupt. Es wird wirklich nur benötigt, wenn Sie es für die zukünftige Verwendung speichern müssen, z. B. wenn Sie seinen Wert mehrmals untersuchen müssen (in diesem Fall würden Sie seinen Wert einer Variablen zuweisen und eine Reihe von Tests für diese Variable durchführen).
Kommentare
- Ein Nachteil der Verwendung von
return
ist der für Funktionen wief() (...; cmd; return)
verhindert die Optimierung, die einige Shells durchführen, um diecmd
im selben Prozess wie die Subshell auszuführen. Bei vielen Shells bedeutet dies auch, dass der Exit-Status der Funktion ‚ nicht die Information enthält, dasscmd
getötet wurde, wenn dies der Fall war (Die meisten Shells können ‚ diese Informationen ohnehin nicht abrufen.) - Beachten Sie, dass mit pdksh und einigen seiner Ableitungen (wie OpenBSD
sh
oderposh
), ‚ benötigenreturn -- "$?"
, wenn es eine gibt Chance, dass der letzte Befehl eine Funktion war, die eine negative Zahl zurückgegeben hat.mksh
(ebenfalls basierend auf pdksh) verbietet Funktionen die Rückgabe negativer Werte. - danke dies hilft, ich denke ich
Ich verstehe nicht, wie return x
anders funktioniert alsexit x
… das einzige, was ich weiß, ist, dassreturn x
beendet den aktuellen Prozess nicht. - @AlexanderMills Nun, ‚ ist das, was ich gesagt habe:
return
wird verwendet, um von einer Funktion oder einem Punktskript zurückzukehren.exit
macht etwas völlig anderes (beendet einen Prozess). - Ja, das macht Sinn. Ich denke, ich fange an, dies besser in den Griff zu bekommen.
Antwort
Auf der Manpage bash(1)
:
Bei Ausführung ist der Exit-Status einer Funktion der Exit-Status des zuletzt im Body ausgeführten Befehls.
Kommentare
- richtig, und eine Konsequenz könnte sein, dass die return-Anweisung nichts anderes als der Exit-Status ist?
- Ich denke
return
ist ein eingebauter Befehl – obwohlreturn 1
sich vonexit 1
usw. unterscheidet, also - “ return [n]: Bewirkt, dass eine Funktion die Ausführung beendet und den von n angegebenen Wert an ihren Aufrufer zurückgibt. Wenn n weggelassen wird, ist der Rückgabestatus der des letzten im Funktionskörper ausgeführten Befehls. “ (ibid) Also
return
erzwingt den Exit-Status einer Funktion auf einen bestimmten Wert, falls angegeben. - @AlexandwrMills Ja,
return
undexit
sind beide integriert, außer dassreturn
nur innerhalb der Funktion verwendet werden kann. Sie können ‚ ein Skript nicht mitreturn
beenden. Der Beendigungsstatus ist der Wert, den der Befehl zurückgibt.return
ist ein Befehl, der diesen Wert zurückgibt. “ return-Anweisung ist also nichts anderes als der Exit-Status “ ist einfach nicht ganz genau. Einer ist ein Wert, der andere ist Befehl plus Wert. - @AlexanderMills,
return
gibt von der Funktion zurück,exit
verlässt die gesamte Shell. Es ist ‚ genau das gleiche wie in, sagen Sie C mitreturn
vs.exit(n)
, oderreturn
vs.sys.exit()
in Python.
Antwort
Ich werde den bereits gegebenen Antworten nur ein paar Hinweise zur Vorsicht hinzufügen:
-
Obwohl
return
aus syntaktischer Sicht eine ganz besondere Bedeutung für die Shell hat, handelt es sich um einen in die Shell integrierten Befehl und eine return-Anweisung wird wie jeder andere einfache Befehl analysiert. Dies bedeutet, dass$?
, wenn sie nicht in Anführungszeichen gesetzt ist, wie im Argument eines anderen Befehls split + globSie müssen also $?
zitieren, um dies zu vermeiden:return "$?"
-
return
akzeptiert normalerweise keine Option (ksh93
„s akzeptiert die üblichen--help
,--man
,--author
… obwohl). Das einzige erwartete Argument (optional) ist der Rückkehrcode. Der Bereich der akzeptierten Rückkehrcodes variiert von Shell zu Shell und ob ein Wert außerhalb von 0..255 in
variiert ebenfalls von Shell zu Shell. Weitere Informationen hierzu finden Sie unter Standard-Exit-Code, wenn der Prozess beendet wird? .
Die meisten Shells akzeptieren negative Zahlen (schließlich wurde das Argument an übergeben Der Systemaufruf _exit()
/ exitgroup()
ist ein int
, also mit Werten, die mindestens – 2 31 bis 2 31 -1, daher ist es nur sinnvoll, dass Shells den gleichen Bereich für ihre Funktionen akzeptieren.
Die meisten Shells verwenden das waitpid()
und co. API zum Abrufen dieses Beendigungsstatus. In diesem Fall wird sie jedoch auf eine Zahl zwischen 0 und 255 gekürzt, wenn in $?
gespeichert wird. Auch wenn eine Funktion aufgerufen wird beinhaltet nicht das Laichen eines Prozesses und verwendet waitpid()
, um seinen Exit-Status abzurufen, da alles im selben Prozess ausgeführt wird. Viele Shells ahmen auch nach, dass waitpid()
Verhalten beim Aufrufen von Funktionen. Dies bedeutet, dass $?
auch dann eine positive Zahl enthält, wenn Sie return
mit einem negativen Wert aufrufen.
Nun, unter den Shells, deren return
negative Zahlen akzeptiert (ksh88, ksh93, bash, zsh, pdksh und andere Ableitungen als mksh, yash), gibt es einige ( pdksh und yash), die als return -- -123
geschrieben werden müssen, andernfalls wird -123
als drei -1
, -2
, -3
ungültige Optionen.
Wie pdksh und sein de Rivative (wie OpenBSD sh
oder posh
) behalten die negative Zahl in $?
bei Das Ausführen von return "$?"
würde fehlschlagen, wenn $?
eine negative Zahl enthält (was passieren würde, wenn der letzte Ausführungsbefehl eine Funktion wäre, die eine negative Zahl zurückgibt ).
return -- "$?"
wäre in diesen Shells besser. Beachten Sie jedoch, dass diese Syntax zwar von den meisten Shells unterstützt wird, jedoch nicht POSIX ist und in der Praxis nicht von mksh
und Aschederivaten unterstützt wird.
Zusammenfassend lässt sich also sagen, mit Bei pdksh-basierten Shells können Sie negative Zahlen in Argumenten für Funktionen verwenden. Wenn Sie dies jedoch tun, funktioniert return "$@"
nicht. In anderen Shells return "$@"
funktioniert und Sie sollten vermeiden, negative Zahlen (oder Zahlen außerhalb von 0..255) als Argumente für return
zu verwenden.
In allen mir bekannten Shells führt das Aufrufen von return
aus einer in einer Funktion ausgeführten Subshell dazu, dass die Subshell beendet wird (mit dem angegebenen Exit-Status, falls vorhanden, oder dem des letzten Befehls run), führt aber ansonsten nicht zu einer Rückkehr der Funktion (für mich ist unklar, ob POSIX Ihnen diese Garantie gewährt. Einige argumentieren, dass exit
anstelle von Exit-Subshells verwendet werden sollte Innenfunktionen). Zum Beispiel gibt
f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?"
Folgendes aus:
still inside f. Exit status: 3 f exit status: 0
Antwort
Ja, der implizite Rückgabewert einer Funktion ist der Exit-Status des zuletzt ausgeführten Befehl. Das gilt auch an jedem Punkt eines Shell-Skripts. Zu jedem Zeitpunkt in der Skriptausführungssequenz ist der aktuelle Beendigungsstatus der Beendigungsstatus des zuletzt ausgeführten Befehls. Sogar Befehl, der als Teil einer Variablenzuweisung ausgeführt wird: var=$(exit 34)
. Der Unterschied zu Funktionen besteht darin, dass eine Funktion den Exit-Status am Ende der Ausführung der Funktion ändern kann.
Die alternative Möglichkeit, den „aktuellen Exit-Status“ zu ändern, besteht darin, eine Sub-Shell zu starten und mit zu beenden Erforderlicher Exit-Status:
$ $(exit 34) $ echo "$?" 34
Und ja, der Exit-Status Erweiterung muss in Anführungszeichen gesetzt werden:
$ IFS="123" $ $(exit 34) $ echo $? 4
A (exit 34)
funktioniert ebenfalls.
Einige mögen argumentieren, dass ein robusteres Konstrukt $(return 34)
sein sollte und dass ein Exit das ausgeführte Skript „beenden“ sollte. $(return 34)
funktioniert jedoch nicht mit einer -Version von bash. Es ist also nicht portabel.
Der sicherste Weg, einen Exit-Status festzulegen, besteht darin, ihn so zu verwenden, wie er für die Arbeit, Definition und return
einer Funktion entwickelt wurde :
exitstatus(){ return "${1:-"$?"}"; }
Also am Ende einer Funktion. Es ist genau gleichbedeutend mit entweder nichts oder return
oder return "$?"
. Das Ende einer Funktion muss nicht die „letzte Codezeile einer Funktion“ bedeuten.
#!/bin/sh exitstatus(){ a="${1:-"$?"}"; return "$a"; } gmx(){ if [ "$1" = "one" ]; then printf "foo "; exitstatus 78 return "$?" elif [ "$1" = "two" ]; then printf "baz "; exitstatus 89 return else printf "baz "; exitstatus 90 fi }
Gibt Folgendes aus:
$ ./script foo 78 baz 89 baz 90
Die einzige praktische Verwendung für "$?"
besteht darin, entweder den Wert echo "$?"
zu drucken oder zu speichern es in einer Variablen (da es ein kurzlebiger Wert ist und sich mit jedem ausgeführten Befehl ändert): exitstatus=$?
(denken Sie daran, die Variable in Befehlen wie export EXITSTATUS="$?"
.
Im Befehl return
liegt der gültige Wertebereich im Allgemeinen zwischen 0 und 255, aber verstehen Sie die Werte von 126 + n
werden von einigen Shells verwendet, um einen speziellen Ausgangsstatus zu signalisieren. Daher wird generell empfohlen, 0-125 zu verwenden.