it-swarm.com.de

Es gibt keine Möglichkeit, das Bash-Skript zu beenden, das Terminal jedoch nicht zu verlassen

Wenn ich den Befehl exit in einem Shell-Skript verwende, beendet das Skript das Terminal (die Aufforderung). Gibt es eine Möglichkeit, ein Skript zu beenden und dann im Terminal zu bleiben?

Es wird erwartet, dass mein Skript run.sh ausgeführt wird, indem es direkt oder aus einem anderen Skript stammt.

EDIT: Um genauer zu sein, gibt es zwei Skripte run2.sh as

...
. run.sh
echo "place A"
...

und run.sh as

...
exit
...

wenn ich es mit . run2.sh starte und exit codeline in run.sh klicke, möchte ich, dass es zum Terminal stoppt und dort bleibt. Mit exit wird jedoch das gesamte Terminal geschlossen. 

PS: Ich habe versucht, return zu verwenden, aber echo-Codeline wird trotzdem ausgeführt.

143
Richard

Das "Problem" ist wirklich, dass Sie das Skript beschaffen und nicht ausführen. Wenn Sie eine Datei als Quelle verwenden, wird der Inhalt in der aktuellen Shell ausgeführt, anstatt eine Subshell aufzurufen. Daher wirkt sich alles, einschließlich exit, auf die aktuelle Shell aus.

Anstelle von exit möchten Sie return verwenden.

211
Dominik Honnef

Ja; Sie können return anstelle von exit verwenden. Der Hauptzweck besteht darin, von einer Shell-Funktion zurückzukehren. Wenn Sie sie jedoch in einem source- d-Skript verwenden, wird dieses Skript zurückgegeben.

Wie §4.1 "Bourne Shell Builtins" des Bash-Referenzhandbuchs schreibt es:

     return [n]

Eine Shell-Funktion mit dem Rückgabewert n beenden. Wenn n nicht angegeben wird, ist der Rückgabewert der Beendigungsstatus von letzter Befehl in der Funktion ausgeführt. Dies kann auch verwendet werden, um die Ausführung eines ausgeführten Skripts zu beenden mit dem eingebauten . (oder source), wobei entweder n oder .__ zurückgegeben wird. Der Exit-Status des letzten innerhalb des Skripts ausgeführten Befehls als Exit Status des Skripts. Jeder Befehl, der der RETURN-Falle zugeordnet ist, wird ausgeführt bevor die Ausführung nach der Funktion oder dem Skript fortgesetzt wird. Der Rückgabestatus ist nicht Null, wenn return außerhalb einer Funktion verwendet wird und nicht während der Ausführung eines Skripts durch . oder source.

32
ruakh

Anstatt den Code mit . run2.sh auszuführen, können Sie das Skript mit sh run2.sh oder bash run2.sh ausführen.
Eine neue Instanz wird geöffnet, um das Skript auszuführen. Am Ende des Skripts wird es geschlossen, wobei die andere Shell geöffnet bleibt

9
Viorel Mirea

Dies ist genau so, als würden Sie eine Run-Funktion in Ihr Skript run2.sh ..__ einfügen. Sie verwenden Exit-Code innerhalb von run, während Sie Ihre run2.sh-Datei in die bash-tty ..__-Quelle laden Ihr Skript und geben Sie dem run2.sh die Berechtigung, den Terminator zu beenden .___ Dann kann die Run-Funktion den Teminator beenden.

    #! /bin/sh
    # use . run2.sh

    run()
    {
        echo "this is run"
        #return 0
        exit 0
    }

    echo "this is begin"
    run
    echo "this is end"

Wie auch immer, ich stimme mit Kaz zu, dass es ein Designproblem ist.

2
Umae

Ich denke, dass dies passiert, weil Sie es im Quellmodus Mit dem Punkt ausführen

. myscript.sh

Sie sollten das in einer Subshell ausführen:

/full/path/to/script/myscript.sh

'source' http://ss64.com/bash/source.html

1
JBoy

Ich hatte das gleiche Problem und aus den obigen Antworten und dem, was ich verstand, war, was letztendlich für mich funktionierte

  1. Haben Sie eine Shebang-Zeile, die das beabsichtigte Skript aufruft, zum Beispiel #!/bin/bash verwendet bash, um das Skript auszuführen

Ich habe Skripte mit beiden Arten von Shebang. Aus diesem Grund mit sh oder. war nicht zuverlässig, da dies zu einer fehlerhaften Ausführung führte (wie wenn das Skript nicht vollständig ausgeführt wurde)

Die Antwort war also

    • stellen Sie sicher, dass das Skript einen Shebang hat, damit kein Zweifel über den beabsichtigten Handler besteht
    • chmod die .sh-Datei, damit sie ausgeführt werden kann
    • rufen Sie es direkt ohne sh oder auf.

./myscript.sh

Hoffe das hilft jemandem mit ähnlichen Anforderungen/Umständen

1
gk_2000

Es ist richtig, dass verwandte und ausgeführte Skripte return vs. exit verwenden, um dieselbe Sitzung offen zu halten, wie andere bemerkt haben.

Hier ist ein verwandter Tipp, wenn Sie jemals ein Skript wünschen, das die Sitzung offen halten soll, unabhängig davon, ob sie verwendet wird oder nicht.

Das folgende Beispiel kann direkt wie foo.sh ausgeführt oder als . foo.sh/source foo.sh ausgegeben werden. In beiden Fällen bleibt die Sitzung nach dem "Beenden" geöffnet. Die Zeichenfolge [email protected] wird übergeben, damit die Funktion Zugriff auf die Argumente des äußeren Skripts hat.

#!/bin/sh
foo(){
    read -p "Would you like to XYZ? (Y/N): " response;
    [ $response != 'y' ] && return 1;
    echo "XYZ complete (args [email protected]).";
    return 0;
    echo "This line will never execute.";
}
foo "[email protected]";

Terminalergebnis:

$ foo.sh
$ Möchten Sie XYZ? (J/N): n
$. foo.sh
$ Möchten Sie XYZ? (J/N): n
$ |
(Terminalfenster bleibt geöffnet und akzeptiert zusätzliche Eingaben)

Dies kann nützlich sein, um Skriptänderungen in einem einzigen Terminal schnell zu testen, während Sie während der Arbeit eine Reihe von Code-Code unter dem Haupt-exit/return aufbewahren. Code könnte in gewissem Sinne auch portabler werden (wenn Sie viele Skripte haben, die auf unterschiedliche Weise aufgerufen werden können oder nicht), obwohl es viel weniger umständlich ist, einfach return und exit zu verwenden .

1
Beejor

Ich glaube, Sie könnten verwirrt sein, wenn Sie ein Skript ausführen.

Wenn Sie sh verwenden, um ein Skript auszuführen, sagen Sie sh ./run2.sh. Auch wenn das eingebettete Skript mit exit endet, bleibt Ihr Terminalfenster erhalten.

Wenn Sie jedoch . oder source verwenden, wird Ihr Terminalfenster ebenfalls beendet/geschlossen, wenn der Index endet.

weitere Informationen finden Sie unter Was ist der Unterschied zwischen der Verwendung von sh und source?

0
karl li

Um ein Skript zu schreiben, das kugelsicher ist und entweder als Shell-Skript ausgeführt oder als RC-Datei bereitgestellt wurde, kann das Skript $0 und $BASH_SOURCE prüfen und vergleichen, ob exit sicher verwendet werden kann.

Hier ist ein kurzer Codeausschnitt

[ "X$(basename $0)" = "X$(basename $BASH_SOURCE)" ] && \
    echo "***** executing $name_src as a Shell script *****" || \
    echo "..... sourcing $name_src ....."

Sie können einen zusätzlichen Exit-Befehl nach dem Return-Befehl hinzufügen, sodass er sowohl für die Ausführung des Skripts über die Befehlszeile als auch für das Sourcing vom Terminal verwendet werden kann.

Beispiel für einen Exit-Code im Skript:

   if [ $# -lt 2 ]; then
     echo "Needs at least two arguments"
     return 1 2>/dev/null
     exit 1
   fi

Die Zeile mit dem Befehl exit wird nicht aufgerufen, wenn Sie das Skript nach dem Befehl return erstellen.

Wenn Sie das Skript ausführen, gibt der Befehl return einen Fehler aus. Daher unterdrücken wir die Fehlermeldung, indem wir sie an /dev/null weiterleiten.

0
noname

Stellen Sie außerdem sicher, dass Sie den erwarteten Rückgabewert zurückgeben. Andernfalls, wenn Sie exit verwenden, wenn Sie auf einen Exit stoßen, wird er von Ihrer Basis-Shell beendet, da source keinen anderen Prozess (Instanz) erstellt.

0
coder23

wenn Ihr Terminalemulator keinen -hold hat, können Sie ein Quelltext-Skript bereinigen und das Terminal mit folgendem Befehl halten:

#!/bin/sh
sed "s/exit/return/g" script >/tmp/script
. /tmp/script
read

ansonsten können Sie $TERM -hold -e script verwenden

0
technosaurus