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 errtrace
trap ERR
これにより、呼び出しスタック内のすべての関数がスクリプトエラー(ゼロ以外の終了コードを使用)によって終了するため、カスケードエラーレポートを受け取ることができます。
ERR
失敗が致命的ではないと見なされる状況(たとえば、if
またはwhile
)では、シェル関数を呼び出しても失敗はトリガーされません。このような状況ではスタックトレースが表示されない場合がありますが、バージョンによってどのように異なるかはわかりません。