I was writing a script and then came across a odd problem. If I'd source a script that contains a bunch of functions that may call an error function which outputs a string and then exits, it will exit my shell. I know why it does it. It is because a function call is in the same process space as the caller (at least it is in bash), so the exit within the function terminates the current process with the exit code provided. Example:
error() { echo $1 exit 1 } fn() { if [ $# == 0 ]; then error "Insufficient parameters." fi # do stuff } $ fn Insufficient parameters. [shell terminates]
So my question is, can I exit all functions in the function stack without terminating the current shell and without spawning a new subshell?
Thanks
Use return . The return bash builtin will exit the sourced script without stopping the calling (parent/sourcing) script. Causes a function to stop executing and return the value specified by n to its caller.
exit exits the calling shell or shell script with the exit status specified by n . If you omit n , the exit status is that of the last command executed (an end-of-file exits the shell). return exits a function with the return value specified by n . If you omit n , the return status is that of the last command executed.
After a function returns, $? gives the exit status of the last command executed in the function. This is Bash's way of giving functions a "return value." [ 1] Following the execution of a pipe, a $? gives the exit status of the last command executed.
exit-Issuing the exit command at the shell prompt will cause the shell to exit. In some cases, if you have jobs running in the background, the shell will remind you that they are running and simply return you to the command prompt. In this case, issuing exit again will terminate those jobs and exit the shell.
To exit the function stack without exiting shell one can use the command:
kill -INT $$
As pizza stated, this is like pressing Ctrl-C, which will stop the current script from running and drop you down to the command prompt.
Note: the only reason I didn't select pizza's answer is because this was buried in his/her answer and not answered directly.
you can do a
exit() { return $1;}
then
source ./your_script
In answer to the skeptics, this only affect the current shell, it does not affect shells you spawn.
The more informative form can be
exit() { local ans local line read -p "You really want to exit this? " line ans=$(echo $line) case "$ans" in Y);; y);; *)kill -INT $$;; esac unset -f exit exit $1 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With