## CONSTANTS CURRENT_SOURCE="${BASH_SOURCE[0]}" # TODO: read and understand the catch function # https://stackoverflow.com/a/59592881/5018486 ## FUNCTIONS function exit { local error_code stack_lines stack_functions stack_sources error_code=${1:-0} stack_lines=("${BASH_LINENO[@]}") stack_functions=("${FUNCNAME[@]}") stack_sources=("${BASH_SOURCE[@]}") unset stack_functions[0] unset stack_sources[0] unset stack_lines[-1] # # # remove 1 on head list # [[ ${#stack_lines[@]} > 0 && ${stack_lines[0]} == 1 ]] && unset stack_lines[0] # # # remove 0 on tail list # [[ ${#stack_lines[@]} > 0 && ${stack_lines[-1]} == 0 ]] && unset stack_lines[-1] rm $script if [[ $error_code > 0 ]]; then printf "\nEXIT #${error_code} due to error at line ${stack_lines} : \n-----------------------------------------\n" [[ -s /tmp/error ]] && echo -ne 'CAUSE:\t\t' && cat /tmp/error echo -e "FUNCNAME:\t${stack_functions[@]}" >&2 # inner outer main echo -e "BASH_SOURCE:\t${stack_sources[@]}" >&2 echo -e "BASH_LINENO:\t${stack_lines[@]}" >&2 trap - ERR TERM INT EXIT builtin exit "${error_code}" else echo __REAL_SUCCESS fi } function raise_error { message=${1:-an undefined error has occured!} code=${2:-1} echo "error ${code}: ${message}" >&2 trap - ERR TERM INT EXIT exit $code } # MAIN _BACKTRACE=${_BACKTRACE:-false} # echo "_BACKTRACE=${_BACKTRACE}" # a bit of magic: prevent performing the original script and rather running the backtrace version ${_BACKTRACE} && builtin exit set -TEue trap 'exit $?' ERR TERM INT EXIT # echo "current: ${BASH_SOURCE[-1]}" # echo "ARGV : $@" export _BACKTRACE=true source=${BASH_SOURCE[-1]} script="${source}.backtrace" cp $source $script # prepend the set Strict command sed -i '1s/.*/set -TEue/' $script # a bit of magic: save stderr into /tmp/error while outputing stdout! { $script 3>&1 1>&2 2>&3 | tee /tmp/error } 2>/dev/null >/dev/null # SOME VARIANTS (which does not work actually) # ---------- # exec ${BASH_SOURCE[-1]} $* 2>/tmp/error # eval $(<${BASH_SOURCE[-1]}) $* 2>/tmp/error # eval $(<$script) $* 2>&1 >/tmp/error # $script $* 2>&1 >>/tmp/error # ERROR=$($script 3>&1 1>&2 2>&3 | tee /tmp/error)