Wyjdź z funkcji bash, a nie z terminala

12

Mam skrypt bash, jak poniżej, który instaluje Zookeeper, ale tylko jeśli nie jest już zainstalowany.

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

W zaznaczonym wierszu <<<< here, jeśli zookeeper jest już zainstalowany, chcę wyjść ze skryptu poniżej. Ale użycie exitpowoduje wyjście z samego terminala.

prayagupd
źródło
1
Jak uruchomić ten skrypt?
Benoit
2
użyj return 1zamiastexit 1
polym

Odpowiedzi:

21

TL; DR

Użyj returnzamiast exitAND i uruchom skrypt za pomocą source your-script.shaka.. your-script.sh

Pełne szczegóły

Jeśli uruchamiasz skrypt z exitinstrukcją, musisz go uruchomić jako dziecko twojego obecnego dziecka.

Jeśli uruchomisz go w bieżącej powłoce rozpoczętej przez sesję terminalową (użycie . ./<scriptname>dowolnej exitspowoduje zamknięcie głównej powłoki, tej rozpoczętej wzdłuż sesji terminalowej.

Gdybyś uruchomił skrypt jak bash ./<scriptname>(lub jakakolwiek inna powłoka zamiast bash ), wtedy exitzatrzymałbyś swoją powłokę potomną, a nie tę używaną przez twój terminal.

Jeśli skrypt ma uprawnienia do wykonywania, wykonanie go bezpośrednio bez podania nazwy powłoki spowoduje wykonanie go również w powłoce podrzędnej.

Użycie returnzamiast exitpozwoli ci nadal uruchamiać skrypt . ./<script name>bez zamykania bieżącej powłoki. Ale musisz użyć, returnaby wyjść tylko z funkcji lub skryptu źródłowego (skrypt został uruchomiony przy użyciu . ./<scriptname>składni).

Benoit
źródło
returnNIE zatrzyma pliku skryptu
Nam G VU
@NamGVU Właściwe jest powrót zamiast wychodzenia. Zakładając, że źródło pliku, a następnie wywołanie funkcji (funkcja exit/ returnw funkcji nie zostanie wywołana podczas pobierania danego pliku), sesja powłoki zakończy się (wraz z terminalem), jeśli funkcja zostanie użyta exit. Przy pomocy returnobsługiwałby kontrolę z powrotem do powłoki wywołującej. Zauważ, że jeśli chcesz powrócić ze skryptu źródłowego (o którym tu nie chodzi), returnto również poprawny sposób, aby exitzakończyć sesję powłoki.
Kusalananda
Zależy to od sposobu uruchomienia skryptu na pierwszym miejscu
Nam G VU
@NamGVU W pliku nie ma wywołania funkcji. Sourcing lub uruchomienie pliku nie wywołałoby tej funkcji. Wyjaśnij, w jaki sposób funkcja kończy sesję powłoki i terminal w jakikolwiek inny sposób, niż najpierw wyszukując plik, a następnie wywołując go w terminalu.
Kusalananda
Dzięki za udostępnienie. Myślę, że wtedy nie idziemy za daleko od tematu.
Nam G VU
1

Jedynym sposobem, w jaki dany skrypt jest w stanie zakończyć sesję powłoki (a tym samym terminal), jest pozyskanie skryptu (w celu zainstalowania installZookfunkcji w bieżącej sesji powłoki), a następnie uruchomienie funkcji w powłoce.

Jeśli to, co wyświetlasz, to tylko część większego skryptu zawierającego wywołanie installZookfunkcji, wówczas funkcja może nadal powodować zakończenie terminala tylko wtedy, gdy skrypt jest pozyskiwany , ale nie może być uruchamiana jako zwykły skrypt powłoki.

exitkończy bieżącą sesję powłoki. Po uruchomieniu funkcja exitkończy powłokę, która ją wywołała.

returnzwraca funkcję (lub pobrany plik skryptu). Jeśli funkcja zamiast tego exitużyje return, zwróci kontrolę do środowiska wywołującego (prawdopodobnie interaktywnej powłoki, z której wywołano funkcję) bez wychodzenia z niej.

Jeśli ręcznie uruchomić installZookfunkcję z muszli, to wszystko powinno trzeba zrobić, to zmienić exitsię return. Jeśli w skrypcie znajduje się inny fragment kodu, który wywołuje funkcję (i którego nie wyświetlasz), ten fragment kodu musi dodatkowo zareagować na zwracany status funkcji.

Na przykład

installZook || return

Jeśli to nie było częścią żadnej funkcji w skrypcie, a jeśli pozyskałeś skrypt, zwróci on kontrolę nad powłoką, jeśli funkcja zwróci niezerowy kod wyjścia.

Kusalananda
źródło
0

Zamiast używać exit 1spróbuj użyć return 1.

ryekayo
źródło
1
returnpowróci z InstallZook()funkcji, nie wyjdzie ze skryptu.
Barmar
@Barmar Patrz komentarz powyżej .
Kusalananda