我正在尝试将一些错误检查添加到我的bashrc库中。它们是模块化的,并在for循环中加载:
for rcfile in $BASHRCD/*.bash; do
source "$rcfile"
done
我使用一个标志来启用调试(如果我正在尝试解决问题)。我已经以不同的方式重写了以下函数许多,但是无论如何都没有找到发生错误的 sourced 脚本的名称。我已经尝试禁用pipefail,我已经尝试解析$ rcfile的值,我试图捕获并明确地将参数传递给陷阱等等。我故意没有设置errexit,因为我没有当我有错误时希望我的shell退出 - 我只想要有意义的输出。 :)这就是我现在拥有的:
if [[ ${DEBUG:-0} -eq 1 ]]; then
shopt -s extdebug
set -o errtrace
set -o nounset
set -o pipefail
_err_handler() {
local _ec="$?"
local _cmd="${BASH_COMMAND:-unknown}"
traceback 1
_showed_traceback=t
echo "The command ${_cmd} exited with exit code ${_ec}." 1>&2
}
traceback () {
# Hide the traceback() call.
local -i start=$(( ${1:-0} + 1 ))
local -i end=${#BASH_SOURCE[@]}
local -i i=0
local -i j=0
echo "Traceback (last called is first):" 1>&2
for ((i=${start}; i < ${end}; i++)); do
j=$(( $i - 1 ))
local function="${FUNCNAME[$i]}"
local file="${BASH_SOURCE[$i]}"
local line="${BASH_LINENO[$j]}"
echo " ${function}() in ${file}:${line}" 1>&2
done
}
fi
trap _err_handler ERR
当我尝试加载包含错误的文件时,它会生成如下输出:
/Users/nfarrar/.bashrc
Traceback (last called is first):
source() in /Users/nfarrar/.bashrc:43
source() in /Users/nfarrar/.bash_profile:94
The command source "$rcfile" exited with exit code 1.
bash: SOMEFILE: unbound variable
引用的bashrc行是for循环中的行(如上所示)源$ rcfile。回溯引用了我的.bash_profile,因为.bashrc来自它。这很有用,但我真正想要的是发生错误的源文件中的文件名和行号。
修改
此代码段显示BASH_SOURCE
数组的输出并遍历调用程序堆栈。
_err_trap() {
echo "Number of items in BASH_SOURCE: ${#BASH_SOURCE[@]}"
echo "${BASH_SOURCE[@]}"
i=0;
while caller $i; do
((i++))
done
}
trap _err_trap ERR
它会产生以下输出,表明无法获取源的脚本不在BASH_SOURCE或调用者帧中:
Number of items in BASH_SOURCE: 3
/Users/nfarrar/.bash/lib/debug.bash /Users/nfarrar/.bashrc /Users/nfarrar/.bash_profile
43 source /Users/nfarrar/.bashrc
94 source /Users/nfarrar/.bash_profile
列出的三个项目是: