Quittez la fonction bash, pas le terminal

12

J'ai un script bash comme ci-dessous qui installe zookeeper mais seulement s'il n'est pas déjà installé.

##zookeper
installZook(){

        ZOOK_VERSION="3.4.5"
        ZOOK_TOOL="zookeeper-${ZOOK_VERSION}"
        ZOOK_DOWNLOAD_URL="http://www.us.apache.org/dist/zookeeper/${ZOOK_TOOL}/${ZOOK_TOOL}.tar.gz"

        if [ -e $DEFAULT_INSTALLATION_DEST/${ZOOK_TOOL} ]; then
                echo "${ZOOK_TOOL} alreay installed";
                exit 1;      # <<<< here
        elif [ ! -e $DEFAULT_SOURCE_ROOT/${ZOOK_TOOL}.tar.gz ]; then
                wgetIt $ZOOK_DOWNLOAD_URL
        else
                echo "[info] : $DEFAULT_SOURCE_ROOT/$ZOOK_TOOL already exists"
        fi

        sudo mkdir -p /var/lib/zookeeper
        sudo mkdir -p /var/log/zookeeper

        tarIt "$DEFAULT_SOURCE_ROOT/$ZOOK_TOOL.tar.gz"
        sudo chmod 777 -R $DEFAULT_INSTALLATION_DEST/$ZOOK_TOOL
        cp $DEFAULT_INSTALLATION_DEST/$ZOOK_TOOL/conf/zoo_sample.cfg $DEFAULT_INSTALLATION_DEST/$ZOOK_TOOL/conf/zoo.cfg
cat >> ~/.bash_profile <<'EOF'

  ###############################
  ########### ZOOK ###############
  ###############################
  ZOOK_HOME=/usr/local/zookeper-3.4.5
  export ZOOK_HOME
  export PATH=$PATH:$ZOOK_HOME/bin

EOF
}

À la ligne marquée <<<< here, si zookeeper est déjà installé, ce que je veux, c'est quitter le script en dessous. Mais l'utilisation exitquitte le terminal lui-même.

Prayagupd
la source
1
Comment lancez-vous ce script?
Benoit
2
utiliser à la return 1place deexit 1
polym

Réponses:

21

TL; DR

Utilisez returnau lieu de exitET exécutez votre script avec source your-script.shaka.. your-script.sh

Tous les détails

Si exitvous lancez un script contenant une instruction, vous devez le lancer en tant qu'enfant de votre enfant actuel.

Si vous le lancez à l'intérieur du shell actuel de a commencé avec votre session de terminal (en utilisant . ./<scriptname>any exitfermera le shell principal, celui démarré le long de votre session de terminal.

Si vous aviez lancé votre script comme bash ./<scriptname>(ou tout autre shell au lieu de bash ), alors vous exitauriez arrêté votre shell enfant et non celui utilisé par votre terminal.

Si votre script dispose d'autorisations exécutables, l'exécuter directement sans donner le nom du shell l'exécutera également dans un shell enfant.

Utiliser returnau lieu de exitvous permettra de lancer votre script en utilisant . ./<script name>sans fermer le shell courant. Mais vous devez utiliser returnpour quitter une fonction uniquement ou un script source (script exécuté en utilisant la . ./<scriptname>syntaxe).

Benoit
la source
returnN'arrêtera PAS le fichier de script
Nam G VU
@NamGVU Le retour plutôt que la sortie est la bonne chose à faire. En supposant qu'ils source le fichier et appellent ensuite la fonction (le exit/ returndans la fonction ne serait pas appelé lors de la recherche du fichier donné), la session shell se terminerait (avec le terminal) si la fonction était utilisée exit. Avec return, il gérerait le contrôle vers le shell appelant. Notez que si vous souhaitez revenir à partir d'un script d'origine (dont il ne s'agit pas), returnc'est également la bonne façon de le faire, car cela exitmettrait fin à la session shell.
Kusalananda
Cela dépend de la façon dont vous exécutez le script à la première place
Nam G VU
@NamGVU Il n'y a aucun appel à la fonction dans le fichier. Le simple fait de rechercher ou d'exécuter le fichier n'appellerait pas la fonction. Expliquez comment la fonction met fin à la session shell et au terminal d'une autre manière qu'en commençant par le fichier, puis en l'appelant dans le terminal.
Kusalananda
Thanjs pour le partage. Je pense que nous n'allons pas trop loin du sujet alors.
Nam G VU
1

La seule façon pour le script donné de terminer la session shell (et donc le terminal) est de vous procurer le script (pour installer la installZookfonction dans la session shell actuelle), puis d'exécuter la fonction dans le shell.

Si ce que vous montrez n'est qu'une partie d'un script plus grand contenant un appel à la installZookfonction, alors la fonction ne peut toujours provoquer la terminaison du terminal que si le script provient , mais pas en étant exécuté comme un script shell ordinaire.

exittermine la session shell en cours. Lorsque la fonction s'exécute, exitelle termine le shell qui l'a appelée.

returnrenvoie à partir d'une fonction (ou d'un fichier de script d'origine). Si la fonction, au lieu de exit, était utilisée return, elle retournerait le contrôle à l'environnement appelant (probablement le shell interactif à partir duquel vous avez appelé la fonction) sans le quitter.

Si vous exécutez manuellement la installZookfonction à partir du shell, alors tout ce que vous devez faire est de changer le exiten return. S'il y a un autre morceau de code dans votre script qui appelle la fonction (et que vous ne montrez pas), alors ce morceau de code doit également réagir au statut de retour de la fonction.

Par exemple

installZook || return

Si cela ne faisait partie d'aucune fonction dans le script, et si vous aviez fourni le script, il retournerait le contrôle au shell si la fonction renvoyait un code de sortie différent de zéro.

Kusalananda
la source
0

Au lieu d'utiliser, exit 1essayez d'utiliser return 1.

ryekayo
la source
1
returnreviendra de la InstallZook()fonction, ne quittera pas le script.
Barmar
@Barmar Voir le commentaire ci-dessus .
Kusalananda