Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to exit a bash function that expects a return

Tags:

bash

return

exit

I'm not completely clear on the how/why bash's exit keyword is inconsistant when calling a function that expects a return vs. not expecting a return.

For instance, in the following repro:

#!/bin/bash
exitfunc()
{
  echo "Flag 1"
  exit
}
exitfunc
echo "We should never see this."

We see the output:

$ ./z.bash 
Flag 1

However in this slight modification:

#!/bin/bash
exitfunc()
{
      echo "Flag 1"
      exit
}
foo=exitfunc
echo "We should never see this."

The output shows that the function clearly does not exit the shell.

$ ./z.bash
We should never see this.

It seems that the Flag 1 in the second version is the value stored in foo, possibly to store an error code. My question is, why does exit have this behavior in a function called in this way? Does it open a new shell when a function expects a return? How is one supposed to properly exit one of these functions? Do I just need to check the output value of foo and include exit catchers all the way up the call stack?

Thanks.

like image 318
Bennett Avatar asked Dec 04 '25 13:12

Bennett


1 Answers

When you do foo=exitfunc, you are assigning a string exitfunc to the variable foo, not executing a function. In order to execute the function, you should do foo=$(exitfunc) instead. Then the variable foo will contain the output of the function, "Flag 1". This is known as a command substitution.

The call to exit terminates the subshell within which the function has been executed, not the shell which it was called from. In order to exit the host shell, you can do something like this:

#!/bin/bash
exitfunc()
{
      echo "Flag 1"
      exit 1
}
foo=$(exitfunc) || exit
echo "We never see this."

The exit status is non-zero, so the host shell exits before the last line.

The return code of the function is stored in the variable $?, so if you want to use $foo before exiting, you can do something like this:

#!/bin/bash
exitfunc()
{
      echo "Flag 1"
      exit 1
}
foo=$(exitfunc)
e=$?
echo "$foo"
if [ $e -ne 0 ]; then exit; fi
echo "We never see this."

Output:

Flag 1
like image 142
Tom Fenech Avatar answered Dec 07 '25 06:12

Tom Fenech



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!