2012-06-21 4 views
26

Ich schrieb ein Skript und stieß dann auf ein seltsames Problem. Wenn ich ein Skript mit einer Reihe von Funktionen erhalte, die eine Fehlerfunktion aufrufen, die eine Zeichenfolge ausgibt und dann beendet, wird meine Shell beendet. Ich weiß, warum es das tut. Dies liegt daran, dass sich ein Funktionsaufruf im selben Prozessbereich befindet wie der Aufrufer (zumindest in bash), sodass der Exit innerhalb der Funktion den aktuellen Prozess mit dem angegebenen Beendigungscode beendet. Beispiel:Ausfahrt Funktionsstapel ohne Shell

error() 
{ 
    echo $1 
    exit 1 
} 

fn() 
{ 
    if [ $# == 0 ]; then 
    error "Insufficient parameters." 
    fi 
    # do stuff 
} 

$ fn 
Insufficient parameters. 
[shell terminates] 

Also meine Frage ist, kann ich alle Funktionen in der Funktion Stapel verlassen, ohne die aktuelle Shell beendet wird und ohne einen neuen Sub-Shell Laichen?

Dank

Antwort

30

sein kann, ohne Verlassen Schal die Funktion Stapel verlassen man den Befehl verwendet werden kann:

kill -INT $$ 

Als pizza angegeben

, das ist wie Strg-C drücken, Dadurch wird das aktuelle Skript nicht mehr ausgeführt und Sie werden an die Eingabeaufforderung weitergeleitet.

 

 


Hinweis: Der einzige Grund, warum ich nicht pizza ‚s Antwort ausgewählt haben, weil dies in seiner/ihrer Antwort begraben wurde und nicht direkt beantwortet.

+0

Die folgende "Rückkehr" ist vorzuziehen, wie es scheint: das ist die Funktionalität, die für diesen Zweck in der Schale eingebaut wird. Die Schale zu töten ist unelegant. – JPGConnolly

+2

@JPGConnolly was meinst du mit 'Die folgende" Rückkehr "ist vorzuziehen, scheint es? Wenn Sie die eingebaute 'return'-Anweisung verwenden wollen, dann lesen Sie die Frage nicht, da es keine einfache Möglichkeit gibt, sie so zu verwenden, dass sie innerhalb einer Funktion, die mehrere tiefere Funktionen genannt wird, zurück in die Basis-Shell springt den Rückgabewert jedes Funktionsaufrufs abfragen, was in manchen Fällen nicht praktikabel oder möglich ist. Ein 'kill -INT $$' ist etwas eleganter als die Verwendung von 'return' in diesem Fall. – Adrian

+0

Welchen Wert von $? sieht der Aufrufer der Quellfunktion? Oder beendet es das auch? – Michael

2

mit return Aussage, aber Sie müssen Rückkehr hinzuzufügen, nachdem Fehler Aufruf

+1

Funktionen geben zurück, ohne eine Rückgabeanweisung zu benötigen. –

+1

aber OP möchte, dass die Funktion sofort beendet wird, nicht wenn sie an den unteren Rand des Funktionskörpers gelangt. –

+0

Ich möchte alle Funktionen auf dem Stapel zu beenden. Was bedeutet "aber im if; vor tun Sachen"? – Adrian

1

Die Schale zum Zurückspulen durch viele Funktion nicht wirklich eine Ausnahme Mechanismus haben auf einmal aufruft. Sie müssen nur die Rückgabewerte überprüfen und manuell vollständig zurückgeben.

+0

Ich überprüfe auf dem Weg nach unten. Ich möchte nur alle Funktionen beenden, die gerade ausgeführt werden, ohne die Shell zu verlassen. – Adrian

+1

Das bedeutet, dass Sie 'return' anstelle von' exit' verwenden. Aber was ich mit ganz unten meinte, ist, dass Sie innerhalb jeder Funktion eine getrennte "Rückkehr" durchführen müssen, nicht nur einmal im Innersten. –

+1

Das ist leider nicht sinnvoll, was ich machen wollte. – Adrian

5

Sie müssen zu jeder Ihrer Funktionen return Anweisungen hinzufügen, um den Rückgabewert der aufgerufenen Funktionen zu überprüfen. Das Sourcing einer Datei ist wie das Ausschneiden und Einfügen des Codes in den aktuellen Kontext, mit der geringfügigen Ausnahme von Variablen wie $BASH_SOURCE.

Alternativ können Sie fn als Shell-Skript definieren, so dass 10 tun, was Sie wollen (es sei denn, eine Gabelung ist zu teuer).

+1

Eine Überprüfung aller Funktionsexitwerte ist nicht sinnvoll. Um dieses Problem zu umgehen, lasse ich das Shell-Skript die einzelnen Funktionen aufrufen. Das Verlassen wird also meine Shell nicht verlassen. – Adrian

+0

Sie müssen nicht auf alle Exit-Werte prüfen - Überprüfen Sie, ob es gelungen ist - 'if my_function' - oder ob der Exit-Code ungleich Null ist -' my_function; wenn [$? -ne 0] '. – l0b0

+0

Die Funktion als Shell-Skript zu definieren, ist eine gute Lösung, aber die Verwendung von "exit" in dieser Funktion beendet die Shell. Sie haben recht, wenn Sie "return" verwenden, um die Funktion zu beenden, ohne die Shell zu verlassen. – JPGConnolly

7

können Sie eine

exit() { return $1;} 

dann zu den Skeptikern

source ./your_script 

In Antwort tun dies nur dem aktuell Shell beeinflussen, es beeinflusst Schalen nicht Sie laichen.

Die informative Form

exit() { 
    local ans 
    local line 
    read -p "You really want to exit this? " line 
    ans=$(echo $line) 
    case "$ans" in 
      Y);; 
      y);; 
      *)kill -INT $$;; 
    esac 
    unset -f exit 
    exit $1 
} 
+4

Verstecken/Überschreiben von Buildins ist nie eine sehr gute Idee. – glglgl

+0

Dies ist keine gültige Bash-Syntax. –

+0

es ist gültige Syntax. – pizza

Verwandte Themen