15

I have a bash script as below which installs zookeeper but only if not installed already.

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

At the line marked <<<< here, if zookeeper is already installed, what I want is to exit the script below it. But using exit exits the terminal itself.

2
  • 1
    How do you launch this script ? – Benoit Jun 23 '14 at 13:39
  • 2
    use return 1 instead of exit 1 – polym Jun 23 '14 at 13:39
25

TL;DR

Use return instead of exit AND run your script with source your-script.sh aka. . your-script.sh

Full details

If launching a script with an exit statement in it, you have to launch it as a child of you current child.

If you launch it inside the current shell of started with your terminal session (using . ./<scriptname> any exit will close the main shell, the one started along your terminal session.

If you had launched your script like bash ./<scriptname> (or any other shell instead of bash), then exit would have stopped your child shell and not the one used by your terminal.

If your script has executable permissions, executing it directly without giving the name of the shell will execute it in a child shell too.

Using return instead of exit will allow you to still launch your script using . ./<script name> without closing the current shell. But you need to use return to exit from a function only or a sourced script (script ran using the . ./<scriptname> syntax).

5
  • 1
    return will NOT halt the script file – Nam G VU Feb 11 '19 at 8:27
  • @NamGVU Returning rather than exiting is the correct thing to do. Assuming that they source the file and then call the function (the exit/return in the function would not be called while sourcing the given file), the shell session would terminate (together with the terminal) if the function used exit. With return, it would handle control back to the calling shell. Note that if you want to return from a sourced script (which this is not about), return is the correct way to do that too as exit would terminate the shell session. – Kusalananda Feb 11 '19 at 9:38
  • It depends on how you run the script at first place – Nam G VU Feb 11 '19 at 9:50
  • @NamGVU There is no call to the function in the file. Just sourcing or running the file would not call the function. Explain how the function terminates the shell session and terminal in any other way than by first sourcing the file and then calling it in the terminal. – Kusalananda Feb 11 '19 at 10:07
  • Thanjs for sharing. I think we not going too far from the topic then. – Nam G VU Feb 11 '19 at 10:08
2

The only way that the given script is able to terminate the shell session (and therefore the terminal) is by you sourcing the script (to install the installZook function in the current shell session), and then running the function in the shell.

If what you are showing is only a portion of a larger script containing a call to the installZook function, then the function can still only cause the terminal to terminate if the script is sourced, but not through being run as an ordinary shell script.

exit terminates the current shell session. When the function executes exit it terminates the shell that called it.

return returns from a function (or a sourced script file). If the function, instead of exit, used return, it would return control to the calling environment (probably the interactive shell that you called the function from) without exiting it.

If you manually run the installZook function from the shell, then all you should need to do is to change the exit to return. If there's another piece of code in your script that calls the function (and which you are not showing), then that piece of code needs to additionally react to the return status of the function.

For example

installZook || return

If this was part of no function in the script, and if you sourced the script, it would return control to the shell if the function returned a non-zero exit code.

0

Instead of using exit 1 try using return 1.

2
  • 1
    return will return from the InstallZook() function, not exit the script. – Barmar Jun 23 '14 at 15:00
  • @Barmar See comment above. – Kusalananda Feb 11 '19 at 9:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.