bash:访问陷阱函数中的函数调用堆栈

Doc*_*ger 8 bash function trap error-handling

处理 bash 函数调用堆栈跟踪...

脚本捕获错误并运行callStack()函数。但是在捕获时,它总是显示callStack()函数本身的调用堆栈,而不是发生陷阱的函数,如...

/share/sbin/zimdialog: line 647: status: command not found
    Function call stack ( command.function() ) ...
      /share/sbin/zimdialog.main()
        /share/sbin/include.callStack()
Run Code Online (Sandbox Code Playgroud)

希望获得包含errantFunction()类似内容的堆栈跟踪...

/share/sbin/zimdialog: line 647: status: command not found
    Function call stack ( command.function() ) ...
      /share/sbin/zimdialog.main()
        /share/sbin/zimdialog.errantFunction()
          /share/sbin/include.callStack()
Run Code Online (Sandbox Code Playgroud)

陷阱被编码为...

trap callStack HUP INT QUIT TERM ERR
Run Code Online (Sandbox Code Playgroud)

callStack()函数被编码为...

function callStack () {
  { isNotNull "$1" && isHelp "$1"; } && {
    helpShow 'callStack
    Diagnostics regarding where the call to this function came from'
    return
  }
  local T="${T}  "
  local STACK=
  i=${#FUNCNAME[@]}
  ((--i))
  printf "${T}Function call stack ( command.function() ) ...\n" >&2
  T="${T}  "
  while (( $i >= 0 ))
  do
    STACK+="${T}${BASH_SOURCE[$i]}.${FUNCNAME[$i]}()\n"
    T="${T}  "
    ((--i))
  done
  printf "$STACK" >&2
}
Run Code Online (Sandbox Code Playgroud)

补充:set -E 等不工作

/share/sbin/gshlib...

set -e
set -E
set -T
shopt -s extdebug

trap $(callStack) ERR

function initialize () {
    :
  logstatus                         #<<< ERROR FOR TESTING trap
}
export -f initialize
Run Code Online (Sandbox Code Playgroud)

错误logStatus地命名为logstatus/share/sbin/gshlib.initialize()弹簧trap ERR,我得到的最好的是......

    Function call stack ...
    | /share/sbin/archive.main()
    |   /share/sbin/include.include()
    |     /share/sbin/gshlib.source()
    |       /share/sbin/include.callStack()
/share/sbin/gshlib: line 109: logstatus: command not found
Run Code Online (Sandbox Code Playgroud)

我想要得到的是...

    Function call stack ...
    | /share/sbin/archive.main()
    |   /share/sbin/include.include()
    |     /share/sbin/gshlib.source()
    |       /share/sbin/gshlib.initialize()
    |         /share/sbin/include.callStack()
/share/sbin/gshlib: line 109: logstatus: command not found
Run Code Online (Sandbox Code Playgroud)

ric*_*ici 5

您需要set -E(或set -o errtrace) 以便trap ERR被调用函数继承。

一旦你这样做了,你可能会发现你会得到一个级联错误报告,因为调用堆栈中的每个函数都将被脚本错误终止(带有非零退出代码)。

ERR在失败不被认为是致命的(如ifwhile)的上下文中调用 shell 函数不会触发。在这种情况下,堆栈跟踪可能不会出现,尽管我不确定它是如何特定于版本的。