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

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
}

追加: 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

Springという名前が間違っていて、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

私が得たいのは…

    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

答え1

呼び出された関数を継承するにはset -E(または)が必要です。set -o errtracetrap ERR

これにより、呼び出しスタック内のすべての関数がスクリプトエラー(ゼロ以外の終了コードを使用)によって終了するため、カスケードエラーレポートを受け取ることができます。

ERR失敗が致命的ではないと見なされる状況(たとえば、ifまたはwhile)では、シェル関数を呼び出しても失敗はトリガーされません。このような状況ではスタックトレースが表示されない場合がありますが、バージョンによってどのように異なるかはわかりません。

関連情報