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
returnist der für Funktionen wief() (...; cmd; return)verhindert die Optimierung, die einige Shells durchführen, um diecmdim selben Prozess wie die Subshell auszuführen. Bei vielen Shells bedeutet dies auch, dass der Exit-Status der Funktion ‚ nicht die Information enthält, dasscmdgetö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
shoderposh), ‚ 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 xanders funktioniert alsexit x… das einzige, was ich weiß, ist, dassreturn xbeendet den aktuellen Prozess nicht. - @AlexanderMills Nun, ‚ ist das, was ich gesagt habe:
returnwird verwendet, um von einer Funktion oder einem Punktskript zurückzukehren.exitmacht 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
returnist ein eingebauter Befehl – obwohlreturn 1sich vonexit 1usw. 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
returnerzwingt den Exit-Status einer Funktion auf einen bestimmten Wert, falls angegeben. - @AlexandwrMills Ja,
returnundexitsind beide integriert, außer dassreturnnur innerhalb der Funktion verwendet werden kann. Sie können ‚ ein Skript nicht mitreturnbeenden. Der Beendigungsstatus ist der Wert, den der Befehl zurückgibt.returnist 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,
returngibt von der Funktion zurück,exitverlässt die gesamte Shell. Es ist ‚ genau das gleiche wie in, sagen Sie C mitreturnvs.exit(n), oderreturnvs.sys.exit()in Python.
Antwort
Ich werde den bereits gegebenen Antworten nur ein paar Hinweise zur Vorsicht hinzufügen:
-
Obwohl
returnaus 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 "$?" -
returnakzeptiert 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.