# functions below for for more details and manual error handling. See
# end of file for credits etc.
+# TODO: investigate to see if we can format output betting in case of
+# subshell failure. Right now, we get independent trace from inside and
+# outside of the subshell. Note, errexit + inherit_errexit doesn't have
+# any smarts around this either.
+
#######################################
# err-catch: Setup trap on ERR to print stack trace and exit (or return
# if the shell is interactive). This is the most common use case so we
)
fi
declare -i _err_func_last=0
- shopt -s extdebug
+ if [[ $- != *c* ]]; then
+ shopt -s extdebug
+ fi
# shellcheck disable=SC2154
- trap '_err-bash-trace-interactive $? "$BASH_COMMAND" ${BASH_ARGC[0]} "${BASH_ARGV[@]}" || return $?' ERR
+ trap '_err-bash-trace-interactive $? "${PIPESTATUS[*]}" "$BASH_COMMAND" ${BASH_ARGC[0]} "${BASH_ARGV[@]}" || return $?' ERR
else
# Man bash on exdebug: "If set at shell invocation, arrange to
# execute the debugger". We want to avoid that, but I want this file
#
#######################################
err-exit() {
- local err=$?
+ local err=$? pipestatus="${PIPESTATUS[*]}"
+
# This has to come before most things or vars get changed
local msg="${BASH_SOURCE[1]}:${BASH_LINENO[0]}: \`$BASH_COMMAND' returned $err"
+ if [[ $pipestatus != "$err" ]]; then
+ msg+=", PIPESTATUS: $pipestatus"
+ fi
set +x
if [[ $1 == -* ]]; then
err=${1#-}
# We have these passed to us because they are lost inside the
# function.
ret=$1
- bash_command="$2"
- argc=$(( $3 - 1 ))
- shift 3
+ pipestatus="$2"
+ bash_command="$3"
+ argc=$(( $4 - 1 ))
+ shift 4
argv=("$@")
# The trap returns a nonzero, then gets called again. This condition
- # tells us if we are the first.
- if (( _err_func_last > last )); then
- printf "ERR: \`%s\' returned %s\n" "$bash_command" $ret >&2
+ # tells us if is that has happened by checking if we've gone down a
+ # stack level.
+ if (( _err_func_last >= last )); then
+ printf "ERR: \`%s\' returned %s" "$bash_command" $ret >&2
+ if [[ $pipestatus != "$ret" ]]; then
+ printf ", PIPESTATUS: %s" "$pipestatus" >&2
+ fi
+ echo >&2
fi
printf " from \`%s" "${FUNCNAME[1]}" >&2
if shopt extdebug >/dev/null; then