web-dev-qa-db-ja.com

bash:トラップ関数の関数呼び出しスタックにアクセスする

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()
_

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()
_

トラップは次のようにコード化されます...

_trap callStack HUP INT QUIT TERM ERR
_

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
}
_

補足:-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
_

/share/sbin/gshlib.initialize()内でlogStatuslogstatusに誤って名前を付けて、_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
_

私が手に入れたいのは...

_    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
_
7
DocSalvager

必要がある set -E(またはset -o errtrace)そのためtrap ERRは呼び出された関数に継承されます。

これを行うと、呼び出しスタック内の各関数がスクリプトエラーによって(ゼロ以外の終了コードで)終了するため、カスケードエラーレポートが表示される可能性があります。

ERRは、失敗が致命的とは見なされないコンテキスト(ifwhileなど)でのシェル関数の呼び出しによってトリガーされません。このような状況では、スタックトレースはおそらく表示されませんが、バージョン固有であるかどうかはわかりません。

5
rici