#bash has no exceptions: a failing function prints the message
#to stderr (>&2) and returns an exit code that is not 0
sell() {
local cars=("$@")
if ((${#cars[@]} == 0)); then
echo "No cars for sale" >&2
return 1
fi
echo "sold ${cars[0]}"
}
#2>&1 takes the message into the variable, || catches the code
code=0
message=$(sell 2>&1) || code=$?
#message is "No cars for sale"
#code is 1
#exit 1 instead of return 1 ends the whole script,
#in ( ) or $( ) only that subshell
(
echo "fatal error" >&2
exit 2
) 2> /dev/null
exitCode=$?
#exitCode is 2
echo "message is $message"
echo "code is $code"
echo "exitCode is $exitCode"