using a RETURN trap
along with $BASH_COMMAND allows some cleanup and logging.
foo(){
trap '[[ "$BASH_COMMAND" == "return "* ]] && >&2 echo -e "\033[31mfunction $FUNCNAME failed with error-code ${BASH_COMMAND:7}\033[0m"' RETURN
echo something
# ...
return 42
}
foo
however this approach has some downsides (like exposing potential inside functions) - using a subshell with an EXIT-trap
in the form of try,catch,finally is cleaner:
foo2() {
(
try(){
echo something
# ...
return 42
}
catch(){
errno=$?
>&2 echo -en "\033[31m$(type -t ${FUNCNAME[1]}) '${FUNCNAME[1]}' failed with error-code $errno\033[2;31m. Trace:"
for ((i=${#BASH_SOURCE[@]} - 1; i > 0; i-- )); do >&2 echo -n " ➛ ${FUNCNAME[$i]} (${BASH_SOURCE[$i]}:${BASH_LINENO[$i]})"; done
>&2 echo -e "\033[0m"
}
finally(){
:
}
trap finally EXIT; local errno=0; try "$@" || catch; exit $errno
) || return $?
}
foo2