17

My bash script uses a lot of checks like:

if [ something bad ] ; then
    echo "error message"
    exit 1
fi

I have found out that if the user executes it via source my-script.sh rather than ./my-script.sh, this exit 1 closes the user's shell ! And the user sees no error message !

How do I know that the script is sourced, and how do I exit (with non-zero status code) the sourced script? In general, what can I do about this?

mit
  • 11,083
  • 11
  • 50
  • 74
18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • 2
    It's OK to document whether your script should be sourced or executed, and expect the user to follow that requirement. – chepner Apr 16 '18 at 15:06

3 Answers3

16

It seems there could be 2 parts to this. The first is to know when you're executing in a sourced script instead of an executed one. That can be found in this answer, and for bash they suggest:

[[ "$0" != "$BASH_SOURCE" ]] && sourced=1 || sourced=0

to tell whether or not you are being sourced.

If you are being sourced, you'd want to use return instead of exit.

You could store that function in a variable with something like

if [[ $sourced -eq 1 ]]; then
    ret=return
else
    ret=exit
fi

and then when you want to use the appropriate one you'd just use

$ret 1
Eric Renouf
  • 13,950
  • 3
  • 45
  • 67
6

Define:

[[ "$0" == "$BASH_SOURCE" ]] && ret=exit || ret=return

Use:

$ret 1

arntg
  • 1,557
  • 14
  • 12
3

For those who prefer if:

# find out how the script was invoked
# we don't want to end the user's terminal session!
if [[ "$0" != "$BASH_SOURCE" ]] ; then
  # this script is executed via `source`!
  # An `exit` will close the user's console!
  EXIT=return
else
  # this script is not `source`-d, it's safe to exit via `exit`
  EXIT=exit
fi

and then

$EXIT 1
18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • 1
    Don't use uppercase for your script's private variables. All caps is reserved for system variables. – tripleee Aug 22 '18 at 11:49