Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely exit early from a bash script?

I know there are several SO questions on exit vs. return in bash scripts (e.g. here).

On this topic, but different from existing questions, I believe, I'd like to know if there is a "best practice" for how to safely implement "early return" from a bash script such that the user's current shell is not exited if they source the script.

Answers such as this seem based on "exit", but if the script is sourced, i.e. run with a "." (dot space) prefix, the script runs in the current shell's context, in which case exit statements have the effect of exiting the current shell. I assume this is an undesirable result because a script doesn't know if it is being sourced or being run in a subshell - if the former, the user may unexpectedly have his shell disappear. Is there a way/best practice for early-returns to not exit the current shell if the caller sources it?

E.g. This script...

#! /usr/bin/bash
# f.sh

func()
{
  return 42
}

func
retVal=$?
if [ "${retVal}" -ne 0 ]; then
  exit "${retVal}"
#  return ${retVal} # Can't do this; I get a "./f.sh: line 13: return: can only `return' from a function or sourced script"
fi

echo "don't wanna reach here"

...runs without killing my current shell if it is run from a subshell...

> ./f.sh 
> 

...but kills my current shell if it is sourced:

> . ./f.sh 

One idea that comes to mind is to nest code within coditionals so that there is no explicit exit statement, but my C/C++ bias makes think of early-returns as aesthetically preferable to nested code. Are there other solutions that are truly "early return"?

like image 992
StoneThrow Avatar asked Aug 24 '18 22:08

StoneThrow


People also ask

How do I exit a Bash script early?

To add a conditional statement and exit a for loop early, use a break statement. The following code shows an example of using a break within a for loop: #!/bin/bash for i in {1.. 10} do if [[ $i == '2' ]] then echo "Number $i!" break fi echo "$i" done echo "Done!"

How do I exit from bash shell?

To exit from bash type exit and press ENTER . If your shell prompt is > you may have typed ' or " , to specify a string, as part of a shell command but have not typed another ' or " to close the string. To interrupt the current command press CTRL-C .

Should I exit Bash script?

Often when writing Bash scripts, you will need to terminate the script when a certain condition is met or to take action based on the exit code of a command.

How do you exit a program in shell script?

To end a shell script and set its exit status, use the exit command. Give exit the exit status that your script should have. If it has no explicit status, it will exit with the status of the last command run.

What does exit 0 Do in shell script?

Success is traditionally represented with exit 0 ; failure is normally indicated with a non-zero exit-code. This value can indicate different reasons for failure. For example, GNU grep returns 0 on success, 1 if no matches were found, and 2 for other errors (syntax errors, non-existent input files, etc).


1 Answers

The most common solution to bail out of a script without causing the parent shell to terminate is to try return first. If it fails then exit.

Your code will look like this:

#! /usr/bin/bash
# f.sh

func()
{
  return 42
}

func
retVal=$?
if [ "${retVal}" -ne 0 ]; then
  return ${retVal} 2>/dev/null # this will attempt to return
  exit "${retVal}" # this will get executed if the above failed.
fi

echo "don't wanna reach here"

You can also use return ${retVal} 2>/dev/null || exit "${retVal}".

Hope this helps.

like image 155
alvits Avatar answered Oct 05 '22 06:10

alvits