Выход из функции 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выход из самого терминала.

prayagupd
источник
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>синтаксиса).

Benoit
источник
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

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

Кусалананда
источник
0

Вместо использования exit 1попробуйте использовать return 1.

ryekayo
источник
1
returnвернется из InstallZook()функции, а не выйдет из скрипта.
Бармар
@ Barmar См. Комментарий выше .
Кусалананда