Yes, the implicit return value of a function is the exit status of the last executed command. That is also true at any point of any shell script. At any point in the script execution sequence, the present exit status is the exit status of the last command executed. Even command executed as part of a variable assignment: var=$(exit 34)
. The difference with functions is that a function could change the exit status at the end of execution of the function.
The alternative way to change the "present exit status" is to start a sub shell and exit it with any needed exit status:
$ $(exit 34)
$ echo "$?"
34
And yes, the exit status expansion do need to be quoted:
$ IFS='123'
$ $(exit 34)
$ echo $?
4
A (exit 34)
also work.
Some may argue that a more robust construct should be $(return 34)
, and that an exit should "exit" the script being executed. But $(return 34)
does not work with any version of bash. So, it is not portable.
The safest way to set an exit status is to use it as it was designed to work, define and return
from a function:
exitstatus(){ return "${1:-"$?"}"; }
So, in the end of a function. it is exactly equivalent to have either nothing or return
or return "$?"
. The end of a function does not need to mean the "last code line of a function".
#!/bin/sh
exitstatus(){ a="${1:-"$?"}"; return "$a"; }
gmx(){
if [ "$1" = "one" ]; then
printf 'foo ';
exitstatus 78
return "$?"
elif [ "$1" = "two" ]; then
printf 'baz ';
exitstatus 89
return
else
printf 'baz ';
exitstatus 90
fi
}
Will print:
$ ./script
foo 78
baz 89
baz 90
The only practical use for "$?"
is to either print its value: echo "$?"
or to store it in a variable (as it is an ephemeral value and change with every command executed): exitstatus=$?
(remember to quote the variable in commands like export EXITSTATUS="$?"
.
In the return
command, the valid range of values is generally 0 to 255, but understand that values of 126 + n
are used by some shells to signal special exit status, so, the general recommendation is to use 0-125.