Вийдіть з функції bash, а не з терміналу


12

У мене є bash-скрипт, внизу якого встановлюється zookeeper, але тільки якщо він уже не встановлений.

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

У рядку, позначеному <<<< here, якщо зоопарк уже встановлений, я хочу вийти зі скрипту під ним. Але використання exitвиходів із самого терміналу.


1
Як запустити цей сценарій?
— Бенуа

2
використовувати return 1замістьexit 1
— polym

Відповіді:


21

TL; DR

Використовуйте returnзамість exitІ запускайте свій сценарій з source your-script.shака.. your-script.sh

Повна інформація

Якщо ви запускаєте скрипт із exitзаявою в ньому, ви повинні запустити його як дитина вашої поточної дитини.

Якщо ви запускаєте його всередині поточної оболонки, розпочатої з вашого термінального сеансу (використовуючи . ./<scriptname>будь-яку, exitбуде закрито основну оболонку, та, що розпочалася під час сеансу терміналу.

Якби ви запустили такий сценарій, як bash ./<scriptname>(або будь-яка інша оболонка замість bash ), ви exitзупинили б свою дочірню оболонку, а не ту, яку використовує ваш термінал.

Якщо ваш скрипт має виконавчі дозволи, його виконання безпосередньо без введення імені оболонки виконає і в дочірній оболонці.

Використання returnзамість exitдозволить все-таки запустити сценарій за допомогою, . ./<script name>не закриваючи поточну оболонку. Але вам потрібно скористатися лише returnдля виходу із функції або скрипту (скрипт виконується за допомогою . ./<scriptname>синтаксису).


returnНЕ зупинить файл сценарію
— Nam G VU

@NamGVU Повернення, а не вихід - це правильна річ. Якщо припустити, що вони посилають файл і потім викликають функцію (функція exit/ returnу функцію не буде викликана під час отримання даного файлу), сеанс оболонки припиняється (разом із терміналом), якщо функція використовується exit. З return, він буде обробляти управління назад до оболонки виклику. Зауважте, що якщо ви хочете повернутися з джерела скрипту (про який мова не йде), returnце правильний спосіб зробити це також, як exitі припинить сеанс оболонки.
— Kusalananda

Це залежить від того, як ви запускаєте сценарій на першому місці
— Nam G VU

@NamGVU У файлі немає виклику функції. Просто пошук або запуск файла не викликав би функцію. Поясніть, як функція завершує сеанс оболонки та термінал будь-яким іншим способом, ніж спочатку знайти файл, а потім викликати його в терміналі.
— Kusalananda

Дякую за обмін. Я думаю, що ми не надто далеко пішли від теми.
— Нам Г ВУ

1

Єдиний спосіб, коли даний скрипт здатний припинити сеанс оболонки (і, отже, термінал), - це виправити скрипт (встановити installZookфункцію в поточному сеансі оболонки), а потім виконати функцію в оболонці.

Якщо ви показуєте лише частину більшого скрипту, що містить виклик installZookфункції, функція все ще може призвести до припинення терміналу лише у випадку, коли скрипт буде отриманий , але не через запуск звичайного сценарію оболонки.

exitзавершує поточний сеанс оболонки. Коли функція виконує, exitвона припиняє оболонку, яка її викликала.

returnповертається з функції (або джерела скрипта). Якщо функція замість цього exitвикористовується return, вона повертає контроль до викликового середовища (можливо, інтерактивній оболонці, з якої ви викликали функцію), не виходячи з неї.

Якщо ви вручну запускаєте installZookфункцію з оболонки, то все, що вам потрібно зробити, - це змінити exitна return. Якщо у вашому скрипті є ще один фрагмент коду, який викликає функцію (і який ви не показуєте), тоді цей фрагмент коду повинен додатково реагувати на стан повернення функції.

Наприклад

installZook || return

Якщо це було частиною жодної функції в скрипті, і якщо ви встановили скрипт, він поверне контроль до оболонки, якщо функція поверне ненульовий код виходу.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.