web-dev-qa-db-fra.com

N'importe quel moyen de quitter le script bash, mais pas de quitter le terminal

Lorsque j'utilise la commande exit dans un script Shell, le script met fin au terminal (l'invite). Existe-t-il un moyen de terminer un script et de rester dans le terminal?

Mon script run.sh est censé s'exécuter directement ou directement à partir d'un autre script.

EDIT: Pour être plus précis, il y a deux scripts run2.sh comme

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

et run.sh comme

...
exit
...

quand je le lance par . run2.sh, et s'il touche le code exit dans run.sh, je veux qu'il s'arrête au terminal et y reste Mais en utilisant exit, tout le terminal est fermé. 

PS: J'ai essayé d'utiliser return, mais echo codeline sera toujours exécuté ....

143
Richard

Le "problème" est vraiment que vous effectuez le sourcing et n'exécutez pas le script. Lorsque vous sourcez un fichier, son contenu sera exécuté dans le shell actuel au lieu de créer un sous-shell. Donc, tout, y compris la sortie, affectera le Shell actuel.

Au lieu d'utiliser exit, vous voudrez utiliser return.

211
Dominik Honnef

Oui; vous pouvez utiliser return au lieu de exit. Son objectif principal est de revenir d'une fonction Shell, mais si vous l'utilisez dans un script source-d, il retourne à partir de ce script.

Comme §4.1 "Bourne Shell Builtins" du manuel de référence Bash le dit:

     return [n]

Permet à une fonction Shell de quitter avec la valeur de retour n. Si n n'est pas fourni, la valeur de retour est l'état de sortie du fichier dernière commande exécutée dans la fonction. Ceci peut également être utilisé pour terminer l'exécution d'un script en cours d'exécution avec le . (ou source) intégré, retournant soit n ou l'état de sortie de la dernière commande exécutée dans le script en tant qu'exit statut du script. Toute commande associée à l’interruption RETURN est exécutée avant que l'exécution reprenne après la fonction ou le script. Le statut de retour est différent de zéro si return est utilisé en dehors d'une fonction et pas pendant l'exécution d'un script par . ou source.

32
ruakh

Au lieu d'exécuter le code en utilisant . run2.sh, vous pouvez exécuter le script en utilisant sh run2.sh ou bash run2.sh
Une nouvelle instance sera ouverte pour exécuter le script, puis il sera fermé à la fin du script, laissant l'autre shell ouvert . `

9
Viorel Mirea

C’est comme si vous mettiez une fonction d’exécution dans votre script run2.sh . Vous utilisiez le code de sortie dans exécution pendant que le fichier run2.sh est utilisé dans le bash tty . votre script et donnez à run2.sh .__ son pouvoir de sortir du terminateur . Ensuite, la fonction run a le pouvoir de quitter votre teminator.

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

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

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

Quoi qu'il en soit, j'approuve avec Kaz que c'est un problème de conception.

2
Umae

Je pense que cela se produit parce que vous l'exécutez en mode source Avec le point

. myscript.sh

Vous devriez l'exécuter dans un sous-shell:

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

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

1
JBoy

J'ai eu le même problème et d'après les réponses ci-dessus et d'après ce que j'ai compris, ce qui a finalement fonctionné pour moi a été

  1. Avoir une ligne Shebang qui appelle le script prévu, par exemple, #!/bin/bash utilise bash pour exécuter le script

J'ai des scripts avec les deux types de Shebang. Pour cette raison, en utilisant sh ou. n'était pas fiable, car cela conduisait à une erreur d'exécution (comme lorsque le script ne s'exécute pas complètement)

La réponse était donc

    • assurez-vous que le script a un Shebang, afin qu'il n'y ait aucun doute sur son gestionnaire prévu
    • chmod le fichier .sh afin qu'il puisse être exécuté
    • invoquer directement sans sh ou.

./myscript.sh

J'espère que cela aide quelqu'un avec des exigences/circonstances similaires

1
gk_2000

Il est exact que les scripts sourcés vs exécutés utilisent return contre exit pour garder la même session ouverte, comme d'autres l'ont déjà noté.

Voici un conseil connexe si vous souhaitez un script qui maintienne la session ouverte, qu’il soit ou non source.

L'exemple suivant peut être exécuté directement comme foo.sh ou créé comme . foo.sh/source foo.sh. Dans tous les cas, la session reste ouverte après la "fermeture". La chaîne $@ est transmise de sorte que la fonction ait accès aux arguments du script externe.

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

Résultat final:

$ foo.sh
$ Voulez-vous XYZ? (O/N): n
$. foo.sh
$ Voulez-vous XYZ? (O/N): n
$ |
(la fenêtre du terminal reste ouverte et accepte une entrée supplémentaire)

Cela peut être utile pour tester rapidement les modifications de script dans un seul terminal tout en conservant un tas de code de rebut sous la variable exit/return pendant que vous travaillez. Cela pourrait également rendre le code plus portable dans un sens (si vous avez des tonnes de scripts qui peuvent être appelés de différentes manières), bien qu'il soit beaucoup moins pratique d'utiliser simplement return et exit si nécessaire.

1
Beejor

En fait, je pense que vous pourriez être dérouté par la façon dont vous "exécutez un script".

Si vous utilisez sh pour exécuter un script, par exemple, sh ./run2.sh, même si le script incorporé se termine par exit, votre fenêtre de terminal restera toujours affichée.

Cependant, si vous utilisez . ou source, la fenêtre de votre terminal se ferme/se ferme également à la fin de l'indice.

pour plus de détails, veuillez vous référer à Quelle est la différence entre sh et source?

0
karl li

Pour écrire un script à l'épreuve des balles à exécuter en tant que script Shell ou créé sous forme de fichier rc, le script peut vérifier et comparer $0 et $BASH_SOURCE et déterminer si exit peut être utilisé en toute sécurité.

Voici l'extrait de code court pour cette

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

Vous pouvez ajouter une commande de sortie supplémentaire après la commande de retour afin qu'elle fonctionne à la fois pour l'exécution du script à partir de la ligne de commande et la recherche de sources à partir du terminal.

Exemple de code de sortie dans le script:

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

La ligne avec la commande exit ne sera pas appelée lorsque vous sourcez le script après la commande return.

Lorsque vous exécutez le script, la commande return génère une erreur. Donc, nous supprimons le message d'erreur en le transférant à /dev/null.

0
noname

Assurez-vous également de renvoyer avec la valeur de retour attendue. Sinon, si vous utilisez exit lorsque vous rencontrerez une sortie, il sortira de votre shell de base car la source ne crée pas un autre processus (instance).

0
coder23

si votre émulateur de terminal n'a pas -hold, vous pouvez assainir un script source et conserver le terminal avec:

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

sinon vous pouvez utiliser $TERM -hold -e script

0
technosaurus