Esci dalla funzione bash, non dal terminale


12

Ho uno script bash come di seguito che installa Zookeeper ma solo se non è già installato.

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

Alla riga contrassegnata <<<< here, se zookeeper è già installato, ciò che voglio è uscire dallo script sottostante. Ma l'utilizzo exitesce dal terminale stesso.


1
Come si avvia questo script?
Benoit,

2
usa return 1invece diexit 1
polym il

Risposte:


21

TL; DR

Usa returninvece di exitAND esegui il tuo script con source your-script.shaka.. your-script.sh

Dettagli completi

Se avvii uno script con una exitdichiarazione in esso, devi avviarlo come figlio del tuo attuale figlio.

Se lo avvii nella shell corrente di iniziato con la tua sessione terminale (usando . ./<scriptname>qualsiasi exitchiuderai la shell principale, quella avviata lungo la tua sessione terminale.

Se avessi lanciato il tuo script come bash ./<scriptname>(o qualsiasi altra shell invece di bash ), allora exitavresti fermato la tua shell figlio e non quella usata dal tuo terminale.

Se lo script ha autorizzazioni eseguibili, eseguendolo direttamente senza fornire il nome della shell verrà eseguito anche in una shell figlio.

L'uso di returninvece exitti consentirà di avviare ancora lo script usando . ./<script name>senza chiudere la shell corrente. Ma è necessario utilizzare returnper uscire solo da una funzione o da uno script di origine (lo script è stato eseguito utilizzando la . ./<scriptname>sintassi).


returnNON interromperà il file di script
Nam G VU l'

@NamGVU Tornare piuttosto che uscire è la cosa giusta da fare. Supponendo che abbiano origine il file e quindi chiamino la funzione (la exit/ returnnella funzione non verrebbe chiamata durante l'approvvigionamento del file dato), la sessione della shell terminerebbe (insieme al terminale) se la funzione utilizzata exit. Con return, gestirà il controllo sulla shell chiamante. Si noti che se si desidera tornare da uno script di provenienza (di cui non si tratta), returnè il modo corretto di farlo anche in quanto exitterminerebbe la sessione della shell.
Kusalananda

Dipende da come esegui la sceneggiatura al primo posto
Nam G VU

@NamGVU Non è presente alcuna chiamata alla funzione nel file. Solo il sourcing o l'esecuzione del file non chiamerebbe la funzione. Spiegare in che modo la funzione termina la sessione della shell e il terminale in altro modo rispetto all'approvvigionamento del file e quindi alla sua chiamata nel terminale.
Kusalananda

Grazie per la condivisione. Penso che non andremo troppo lontano dall'argomento allora.
Nam G VU,

1

L'unico modo in cui lo script dato è in grado di terminare la sessione della shell (e quindi il terminale) è procurarsi lo script (per installare la installZookfunzione nella sessione della shell corrente) e quindi eseguire la funzione nella shell.

Se quello che stai mostrando è solo una parte di uno script più grande contenente una chiamata alla installZookfunzione, la funzione può comunque causare la chiusura del terminale solo se lo script è di provenienza , ma non attraverso l'esecuzione come un normale script di shell.

exittermina la sessione di shell corrente. Quando la funzione viene eseguita exit, termina la shell che l'ha chiamata.

returnritorna da una funzione (o da un file di script di provenienza). Se la funzione, invece di exit, utilizzata return, restituirebbe il controllo all'ambiente chiamante (probabilmente la shell interattiva da cui hai chiamato la funzione) senza uscire da essa.

Se esegui manualmente la installZookfunzione dalla shell, tutto ciò che dovresti fare è cambiare exitin return. Se c'è un altro pezzo di codice nel tuo script che chiama la funzione (e che non stai mostrando), allora quel pezzo di codice deve reagire ulteriormente allo stato di ritorno della funzione.

Per esempio

installZook || return

Se questo non faceva parte di nessuna funzione nello script e se lo si era originato, sarebbe tornato il controllo sulla shell se la funzione avesse restituito un codice di uscita diverso da zero.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.