Saia da função bash, não do terminal

12

Eu tenho um script bash como abaixo, que instala o zookeeper, mas apenas se ainda não estiver instalado.

##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
}

Na linha marcada <<<< here, se o zookeeper já estiver instalado, o que eu quero é sair do script abaixo dele. Mas o uso exitsai do próprio terminal.

prayagupd
fonte
1
Como você lança esse script?
Benoit
2
use em return 1vez deexit 1
polym

Respostas:

21

TL; DR

Use em returnvez de exitAND e execute seu script com source your-script.shaka.. your-script.sh

Detalhes completos

Se você iniciar um script com uma exitdeclaração, precisará iniciá-lo como filho do seu filho atual.

Se você iniciá-lo dentro do shell atual iniciado com a sessão do terminal (usando . ./<scriptname>qualquer exitum fechará o shell principal, o iniciado na sessão do terminal).

Se você tivesse lançado seu script como bash ./<scriptname>(ou qualquer outro shell em vez do bash ), exitteria parado o shell filho e não o usado pelo seu terminal.

Se o seu script tiver permissões executáveis, executá-lo diretamente sem fornecer o nome do shell também o executará em um shell filho.

Usar em returnvez de exitpermitirá que você ainda inicie seu script usando . ./<script name>sem fechar o shell atual. Mas você precisa usar returnpara sair apenas de uma função ou de um script de origem (o script foi executado usando a . ./<scriptname>sintaxe).

Benoit
fonte
returnNÃO irá parar o arquivo de script
Nam G VU
@NamGVU Retornar ao invés de sair é a coisa certa a se fazer. Supondo que eles originem o arquivo e depois chamem a função (a função exit/ returnna função não seria chamada ao fornecer o arquivo fornecido), a sessão do shell terminaria (junto com o terminal) se a função fosse usada exit. Com return, controlaria o controle de volta ao shell de chamada. Observe que, se você deseja retornar de um script de origem (do qual não se trata), returné a maneira correta de fazer isso, pois exitterminaria a sessão do shell.
Kusalananda
Depende de como você executa o script em primeiro lugar
Nam G VU
@NamGVU Não há chamada para a função no arquivo. Apenas procurar ou executar o arquivo não chamaria a função. Explique como a função finaliza a sessão e o terminal do shell de qualquer outra maneira que não seja a origem do arquivo e a chamada no terminal.
Kusalananda
Thanjs por compartilhar. Acho que não estamos indo muito longe do assunto então.
Nam G VU
1

A única maneira pela qual o script fornecido pode encerrar a sessão do shell (e, portanto, o terminal) é fornecendo o script (para instalar a installZookfunção na atual sessão do shell) e, em seguida, executando a função no shell.

Se o que você está mostrando é apenas uma parte de um script maior que contém uma chamada para a installZookfunção, a função ainda poderá fazer com que o terminal termine apenas se o script for originado , mas não através da execução como um shell script comum.

exitfinaliza a sessão atual do shell. Quando a função é executada exit, finaliza o shell que a chamou.

returnretorna de uma função (ou um arquivo de script de origem). Se a função, em vez de exit, for usada return, ela retornará o controle ao ambiente de chamada (provavelmente o shell interativo do qual você chamou a função) sem sair dela.

Se você executar manualmente a installZookfunção a partir do shell, tudo o que você precisa fazer é mudar exitpara return. Se houver outro trecho de código em seu script que chame a função (e que você não está mostrando), esse trecho de código precisará reagir adicionalmente ao status de retorno da função.

Por exemplo

installZook || return

Se isso não fizesse parte do script e se você o originasse, ele retornaria o controle ao shell se a função retornasse um código de saída diferente de zero.

Kusalananda
fonte
0

Em vez de usar, exit 1tente usar return 1.

ryekayo
fonte
1
returnretornará da InstallZook()função, não sairá do script.
Barmar
@ Barmar Veja o comentário acima .
Kusalananda