# Basic bash configuration for scripts. # Copyright 2020-2024 Einhard Leichtfuß ################################### ## Error and termination handling # See `/docs/error-handling.md` on limitations and annoyances. ## What to consider as an error. # Accessing unset variables is an error. set -o nounset # No `pipefail` (default). # - Enabling this might, in particular, cause unexpected issues in `if` # statements. # - Enable in a subshell whereever necessary. ## How to act on error. function basic::print_stacktrace() { local -ri offset="$1" local -i i local -a args=() for (( i = offset + 1; i < ${#BASH_SOURCE[@]} - 1; i++ )) do # See also the `caller` bash builtin. args+=( "${BASH_SOURCE[i]} ${BASH_LINENO[i-1]} ${FUNCNAME[i]}" ) done args+=( "${BASH_SOURCE[i]} ${BASH_LINENO[i-1]}
" ) basic::stacktrace_prettyprint "$BASH_SUBSHELL" "${args[@]}" return 0 } # Default function to pretty-print stack trace. # - To be redefined if desired. function basic::stacktrace_prettyprint() { local -ri subshell_id="$1" shift local -i i=$# local msg for msg do printf 'FAILED (%d, %d): %s\n' $subshell_id $((--i)) "$msg" >&2 done return 0 } # On ERR, print stack trace and exit non-zero. trap 'basic::print_stacktrace 0; exit 1' ERR # Inherit traps on ERR. set -o errtrace # Exit on ERR. # - This is mostly made redundant by the ERR trap (which causes an exit). # - However, in some cases, the ERR trap does not apply, while `errexit` does: # - `var[0]=(foo bar)`, when not in a subshell. # - Same for an associative array. # - It is unclear why `errexit` and the ERR trap apply on different # conditions. # - `inherit_errexit` seems indeed irrelevant in our case, but we enable it # for consistency. # - Note: `inherit_errexit` is similar to `errtrace`. # - See also: `/docs/error-handling.md#Array_variables` set -o errexit shopt -s inherit_errexit ## How to act on exit. # Default on_exit() function. # - To be redefined if desired. function basic::on_exit() { return 0 } trap 'basic::on_exit' EXIT ######################## ## Other shell options # Disable globbing; set good defaults for when temporarily enabled. # - `extglob` has an effect regardless. set -o noglob shopt -s nullglob dotglob globasciiranges globstar extglob globskipdots # Print an error message upon `shift`-ing "too far" (causes ERR regardless). shopt -s shift_verbose # Expand associative array subscripts only once. shopt -s assoc_expand_once # Do not let `source' use PATH. shopt -u sourcepath ################## ## Other options # Explicitly set the expected default umask. umask 022 # vi: ft=bash ts=2 sw=0 et