Выход из функции 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, если zookeeper уже установлен, я хочу выйти из скрипта под ним. Но используя exitвыход из самого терминала.


1
Как вы запускаете этот скрипт?
— Бенуа

2
использовать return 1вместоexit 1
— полим

Ответы:


21

TL; DR

Используйте returnвместо exitAND запускать ваш скрипт с помощью source your-script.shaka.. 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это завершит сеанс оболочки.
— Кусалананда

Это зависит от того, как вы запускаете сценарий на первом месте
— Nam G VU

@NamGVU В файле нет вызова функции. Просто поиск или запуск файла не вызовет функцию. Объясните, как функция завершает сеанс оболочки и терминал любым другим способом, кроме как сначала получить файл и затем вызвать его в терминале.
— Кусалананда

Спасибо за обмен. Я думаю, что мы не слишком далеко от темы.
— Nam G VU

1

Единственный способ, которым данный сценарий может прекратить сеанс оболочки (и, следовательно, терминал), состоит в том, что вы запрашиваете сценарий (для установки installZookфункции в текущем сеансе оболочки), а затем запускаете функцию в оболочке.

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

exitзавершает текущий сеанс оболочки. Когда функция выполняется, exitона завершает оболочку, вызвавшую ее.

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

Если вручную запустить installZookфункцию из оболочки, то все , что вам нужно нужно сделать , это изменить exitк return. Если в вашем скрипте есть другой фрагмент кода, который вызывает функцию (и которую вы не показываете), то этот фрагмент кода должен дополнительно отреагировать на состояние возврата функции.

Например

installZook || return

Если это не было частью функции в сценарии, и если вы использовали сценарий, он вернул бы управление оболочке, если функция вернула ненулевой код завершения.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.