我正在尝试向我的 bashrc 库添加一些错误检查。它们是模块化的并加载在 for 循环中:
for rcfile in $BASHRCD/*.bash; do
source "$rcfile"
done
我使用一个标志来启用调试(如果我试图排除故障)。我已经以多种不同的方式重写了以下函数,但无论如何都没有找到提供发生错误的源脚本的名称。我尝试禁用 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
列出的三个项目是:
- .bash/lib/debug.bash(这是来源并包含_err_handler & traceback)
- .bashrc(由 .bash_profile 获取并运行循环以获取目录中的所有文件)
- .bash_profile,其来源 .bashrc