2 # Copyright 2018 Ian Kelling
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
17 # Commentary: Bash stack trace and error handling functions. This file
18 # is meant to be sourced. It loads some functions which you may want to
19 # call manually (see the comments at the start of each one), and then
20 # runs err-catch. See the README file for a slightly longer explanation.
23 #######################################
26 # usage: err-bash-trace [FRAME_START]
28 # This function is called by the other functions which print stack
31 # It does not show function args unless you first run:
33 # which err-catch & err-print do for you.
35 # FRAME_START The frame to start printing on. default=0. Useful when
36 # printing from an ERR trap function to avoid printing
38 #######################################
40 local -i argc_index
=0 frame i start
=${1:-0} max_indent
=8 indent
43 if [[ $
(shopt -p extdebug
) == *-s* ]]; then
46 for ((frame
=0; frame
< ${#FUNCNAME[@]}-1; frame
++)); do
47 argc
=${BASH_ARGC[frame]}
49 ((frame
< start
)) && continue
50 if (( ${#BASH_SOURCE[@]} > 1 )); then
51 source="${BASH_SOURCE[frame+1]}:${BASH_LINENO[frame]}:"
53 indent
=$
((frame-start
+ 1))
54 indent
=$
((indent
< max_indent ? indent
: max_indent
))
55 printf "%${indent}s↳%sin \`%s" '' "$source" "${FUNCNAME[frame]}"
57 for ((i
=argc_index-1
; i
>= argc_index-argc
; i--
)); do
58 printf " %s" "${BASH_ARGV[i]}"
66 #######################################
67 # On error print stack trace and exit
70 # ${_errcatch_cleanup[@]} Optional command & args that will run before exiting
71 #######################################
73 set -E; shopt -s extdebug
78 echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: \`$BASH_COMMAND' returned $err"
80 set -e # err trap does not work within an error trap
81 # note :-: makes this compatible with set -u. shellcheck doesn't understand.
82 "${_errcatch_cleanup[@]:-:}"
83 echo "$0: exiting with code $err"
90 #######################################
91 # Undoes err-catch. turns off exit and stack trace on error.
92 #######################################
94 set +E
+o pipefail
; trap ERR
97 #######################################
98 # On error, print stack trace
99 #######################################
101 # help: on errors: print stack trace
103 # This function depends on err-bash-trace.
105 set -E; shopt -s extdebug
110 echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: \`$BASH_COMMAND' returned $err"
118 #######################################
119 # Print stack trace and exit
121 # Use this instead of the exit command to be more informative.
123 # usage: err-exit [EXIT_CODE] [MESSAGE]
125 # EXIT_CODE Default is 1.
126 # MESSAGE Print MESSAGE to stderr. If only one of EXIT_CODE
127 # and MESSAGE is given, we consider it to be an
128 # exit code if it is a number.
129 #######################################
134 if [[ ${1/[^0-9]/} == "$1" ]]; then
137 printf '%s\n' "$2" >&2
140 printf '%s\n' "$0: $1" >&2
143 echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}"
145 echo "$0: exiting with code $code"
149 # We want this more often than not, so run it now.