1

我正在尝试向我的 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

列出的三个项目是:

  1. .bash/lib/debug.bash(这是来源并包含_err_handler & traceback)
  2. .bashrc(由 .bash_profile 获取并运行循环以获取目录中的所有文件)
  3. .bash_profile,其来源 .bashrc
4

0 回答 0