#!/usr/bin/env bash set -euo pipefail set -o errtrace shopt -s inherit_errexit function printErr { echo -e "\033[0;31mERROR:\033[0m ${1}" } function _exitHandler { local exit_code=$1 if [[ ${exit_code} -ne 0 ]]; then printErr "$0: exit status ${exit_code}" fi } function _errorHandler { local line=$1 local linecallfunc=$2 local command="$3" local funcstack="$4" printErr "$0: '${command}' failed at line ${line}" if [[ ${funcstack} != "::" ]]; then echo -ne "\tin ${funcstack} " if [[ ${linecallfunc} != "" ]]; then echo "called at line ${linecallfunc}" else echo fi fi } _exitHandlers=() _errorHandlers=() function registerExitHandler { _exitHandlers+=("$1") } function registerErrorHandler { _errorHandler+=("$1") } function _callExitHandlers { _exitHandlers+=(_exitHandler) # Add our handler last. for h in "${_exitHandlers[@]}"; do ${h} "$@" done } function _callErrorHandlers { _errorHandlers+=(_errorHandler) # Add our handler last. for h in "${_errorHandlers[@]}"; do ${h} "$@" done } trap '_callErrorHandlers $LINENO $BASH_LINENO "$BASH_COMMAND" $(printf "::%s" ${FUNCNAME[@]:-})' ERR trap '_callExitHandlers $?' EXIT