У меня есть скрипт 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
TL;DR
Используйте return
вместо exit
И запустите свой скрипт с помощью source your-script.sh
aka.. your-script.sh
Полная информация
При запуске скрипта с exit
оператором в нем вам придется запустить его как дочерний элемент текущего дочернего элемента.
Если вы запустите его внутри текущей оболочки, запущенной в ходе сеанса терминала (использование . ./<scriptname>
any exit
закроет основную оболочку, запущенную в ходе сеанса терминала).
Если бы вы запустили свой скрипт как bash ./<scriptname>
(или любую другую оболочку вместоБаш), то exit
остановилась бы ваша дочерняя оболочка, а не та, которая используется вашим терминалом.
Если ваш скрипт имеет права на исполнение, его непосредственное выполнение без указания имени оболочки приведет к его выполнению и в дочерней оболочке.
Использование return
вместо exit
позволит вам по-прежнему запускать ваш скрипт, используя . ./<script name>
без закрытия текущей оболочки. Но вам нужно использовать return
только для выхода из функции или исходного скрипта (скрипт, запущенный с использованием синтаксиса . ./<scriptname>
).
решение2
Вместо использования exit 1
попробуйте использовать return 1
.
решение3
Единственный способ, которым данный скрипт может завершить сеанс оболочки (и, следовательно, терминал), — это получить скрипт (чтобы установить функцию installZook
в текущем сеансе оболочки), а затем запустить функцию в оболочке.
Если то, что вы показываете, является лишь частью более крупного скрипта, содержащего вызов функции installZook
, то функция все равно может вызвать завершение работы терминала, только если скриптполучено, но не путем запуска в качестве обычного скрипта оболочки.
exit
завершает текущую сессию оболочки. Когда функция выполняется, exit
она завершает оболочку, которая ее вызвала.
return
возвращается из функции (или исходного файла скрипта). Если бы функция вместо exit
использовала return
, она бы вернула управление вызывающей среде (вероятно, интерактивной оболочке, из которой вы вызвали функцию) без выхода из нее.
Если вы вручную запуститеinstallZook
функцию из оболочки, то все, что вам нужно сделать, это изменить на exit
. return
Если в вашем скрипте есть другой фрагмент кода, который вызывает функцию (и который вы не показываете), то этот фрагмент кода нужнокроме тогореагировать на возвращаемый статус функции.
Например
installZook || return
Если бы это не было частью функции в скрипте и если бы вы получили скрипт в качестве источника, он бы вернул управление оболочке, если бы функция вернула ненулевой код выхода.