Commit | Line | Data |
---|---|---|
78a1a75c | 1 | #!/bin/bash |
997eb0be IK |
2 | # Copyright 2018 Ian Kelling |
3 | ||
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 | |
7 | ||
8 | # http://www.apache.org/licenses/LICENSE-2.0 | |
9 | ||
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. | |
15 | ||
acd03e1e | 16 | |
acd03e1e IK |
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. | |
21 | ||
997eb0be | 22 | err-allow() { |
acd03e1e IK |
23 | # help: turn off exit and stack trace on error. undoes err-catch |
24 | set +E +o pipefail; trap ERR | |
997eb0be | 25 | } |
364203b2 | 26 | |
997eb0be | 27 | err-bash-trace() { |
acd03e1e IK |
28 | # help: print stack trace |
29 | # | |
30 | # Note: It does not show function args unless you first run: | |
31 | # shopt -s extdebug | |
32 | # err-catch runs this for you. | |
33 | ||
34 | local -i argc_index=0 frame i start=${1:-1} max_indent=8 indent | |
35 | local source | |
36 | local extdebug=false | |
37 | if [[ $(shopt -p extdebug) == *-s* ]]; then | |
38 | extdebug=true | |
39 | fi | |
40 | for ((frame=0; frame < ${#FUNCNAME[@]}-1; frame++)); do | |
41 | argc=${BASH_ARGC[frame]} | |
42 | argc_index+=$argc | |
43 | ((frame < start)) && continue | |
44 | if (( ${#BASH_SOURCE[@]} > 1 )); then | |
45 | source="${BASH_SOURCE[frame+1]}:${BASH_LINENO[frame]}:" | |
46 | fi | |
47 | indent=$((frame-start+1)) | |
48 | indent=$((indent < max_indent ? indent : max_indent)) | |
49 | printf "%${indent}s↳%sin \`%s" '' "$source" "${FUNCNAME[frame]}" | |
50 | if $extdebug; then | |
51 | for ((i=argc_index-1; i >= argc_index-argc; i--)); do | |
52 | printf " %s" "${BASH_ARGV[i]}" | |
53 | done | |
78a1a75c | 54 | fi |
acd03e1e IK |
55 | echo \' |
56 | done | |
78a1a75c | 57 | } |
364203b2 | 58 | |
997eb0be | 59 | err-catch() { |
364203b2 | 60 | # help: on errors: print stack trace and exit |
acd03e1e | 61 | # |
364203b2 | 62 | # You can set "${_errcatch_cleanup[@]}" to a command and it will run before exiting. |
acd03e1e IK |
63 | # This function depends on err-bash-trace. |
64 | ||
65 | set -E; shopt -s extdebug | |
66 | _err-trap() { | |
67 | err=$? | |
68 | exec >&2 | |
69 | set +x | |
70 | echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}:in \`$BASH_COMMAND' returned $err" | |
71 | # err trap does not work within an error trap, the following line: | |
72 | err-bash-trace 2; set -e | |
5cc48c73 | 73 | "${_errcatch_cleanup[@]:-}" # note :- is to be compatible with set -u |
acd03e1e IK |
74 | echo "$0: exiting with code $err" |
75 | exit $err | |
76 | } | |
77 | trap _err-trap ERR | |
78 | set -o pipefail | |
78a1a75c | 79 | } |
364203b2 | 80 | |
997eb0be | 81 | err-exit() { |
acd03e1e IK |
82 | # usage: err-exit [EXIT_CODE] [MESSAGE] |
83 | # help: exit and print stack trace. | |
84 | # | |
85 | # Use this instead of the exit command to be more informative. default | |
86 | # EXIT_CODE is 1. If only one of EXIT_CODE and MESSAGE is given, | |
87 | # we consider it to be an exit code if it is a number. | |
88 | # This function depends on err-bash-trace. | |
89 | ||
90 | exec >&2 | |
91 | code=1 | |
41be570a | 92 | if [[ "$*" ]]; then |
acd03e1e IK |
93 | if [[ ${1/[^0-9]/} == "$1" ]]; then |
94 | code=$1 | |
95 | if [[ $2 ]]; then | |
41be570a | 96 | printf '%s\n' "$2" |
acd03e1e IK |
97 | fi |
98 | else | |
41be570a | 99 | printf '%s\n' "$0: $1" |
78a1a75c | 100 | fi |
acd03e1e IK |
101 | fi |
102 | echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}" | |
103 | err-bash-trace 2 | |
104 | echo "$0: exiting with code $code" | |
105 | exit $err | |
78a1a75c | 106 | } |
364203b2 | 107 | |
acd03e1e | 108 | err-catch |