Skip to content

Commit ec4e8e8

Browse files
committed
feat: add trap_error_info.sh
1 parent b281bbf commit ec4e8e8

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

lib/trap_error_info.sh

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/bin/bash
2+
#
3+
# a common lib to show trapped error info.
4+
#
5+
# provide function `trap_error_info::register_show_error_info_handler` to register
6+
# the error-trap handler which show error info when trapped error.
7+
#
8+
# by default, auto register_show_error_info_handler when source this script;
9+
# disable by define `TRAP_ERROR_NO_AUTO_REGISTER` var
10+
#
11+
#_ source guard start _#
12+
[ -z "${__source_guard_84949D19_1C7A_40AF_BC28_BA5967A0B6CE:+dummy}" ] || return 0
13+
__source_guard_84949D19_1C7A_40AF_BC28_BA5967A0B6CE="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
14+
readonly __source_guard_84949D19_1C7A_40AF_BC28_BA5967A0B6CE
15+
#_ source guard end _#
16+
17+
set -eEu -o pipefail -o functrace
18+
19+
################################################################################
20+
# api functions:
21+
# - trap_error_info::register_show_error_info_handler
22+
# - trap_error_info::show_stack_trace
23+
################################################################################
24+
25+
# trap_error_info::_get_caller_line_no $level
26+
# level = 0 means caller stack
27+
#
28+
# do NOT call this function in sub-shell!
29+
# e.g. $(trap_error_info::_get_caller_line_no)
30+
trap_error_info::_get_caller_line_no() {
31+
local level="$1"
32+
33+
# level 0 of caller means self
34+
# level + 1, to skip `_get_caller_line_no` self
35+
caller $((level + 1)) | {
36+
local line_no _
37+
read -r line_no _
38+
printf "%s" "$line_no"
39+
}
40+
}
41+
42+
# show stack trace with format: func name(source file: line no)
43+
#
44+
# usage:
45+
# trap_error_info::show_stack_trace <hide level> <indent>
46+
#
47+
# about hide level, default contains 2 extra level of implementation:
48+
# - trap_error_info::show_stack_trace
49+
# - trap_error_info::_get_caller_line_no
50+
# set hide level to 2, hide this 2 xtra level of implementation.
51+
#
52+
# do NOT call this function in sub-shell!
53+
trap_error_info::show_stack_trace() {
54+
local hide_level="${1:-0}" indent="${2:-}"
55+
local func_stack_size="${#FUNCNAME[@]}"
56+
57+
local i
58+
for ((i = hide_level; i < func_stack_size; i++)); do
59+
printf "%s%s(%s:" "$indent" "${FUNCNAME[i]}" "${BASH_SOURCE[i]}"
60+
trap_error_info::_get_caller_line_no "$((i - 1))"
61+
printf ")\n"
62+
done
63+
}
64+
65+
# official document of `Bash Variables`, e.g.
66+
# BASH_SOURCE
67+
# BASH_LINENO
68+
# LINENO
69+
# BASH_COMMAND
70+
# https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html
71+
#
72+
# related info:
73+
#
74+
# https://stackoverflow.com/questions/6928946/mysterious-lineno-in-bash-trap-err
75+
# https://stackoverflow.com/questions/64786/error-handling-in-bash
76+
# https://stackoverflow.com/questions/24398691/how-to-get-the-real-line-number-of-a-failing-bash-command
77+
# https://unix.stackexchange.com/questions/39623/trap-err-and-echoing-the-error-line
78+
# https://unix.stackexchange.com/questions/462156/how-do-i-find-the-line-number-in-bash-when-an-error-occured
79+
# https://unix.stackexchange.com/questions/365113/how-to-avoid-error-message-during-the-execution-of-a-bash-script
80+
# https://shapeshed.com/unix-exit-codes/#how-to-suppress-exit-statuses
81+
# https://stackoverflow.com/questions/30078281/raise-error-in-a-bash-script/50265513#50265513
82+
trap_error_info::_show_trapped_error_info() {
83+
echo "$@"
84+
local exit_code="$1" error_code_line="$2"
85+
86+
{
87+
echo '================================================================================'
88+
echo "Trapped error!"
89+
echo
90+
echo "Exit status code: $exit_code"
91+
echo "Stack trace:"
92+
trap_error_info::show_stack_trace 2 " "
93+
echo "Error code line:"
94+
echo " $error_code_line"
95+
echo '================================================================================'
96+
} >&2
97+
}
98+
99+
trap_error_info::register_show_error_info_handler() {
100+
trap 'trap_error_info::_show_trapped_error_info $? "$BASH_COMMAND"' ERR
101+
}
102+
103+
################################################################################
104+
# auto register_show_error_info_handler when source this script;
105+
# disable by define `TRAP_ERROR_NO_AUTO_REGISTER` var
106+
################################################################################
107+
108+
if [ -z "${TRAP_ERROR_NO_AUTO_REGISTER+defined}" ]; then
109+
trap_error_info::register_show_error_info_handler
110+
fi

0 commit comments

Comments
 (0)