以下を含むソースになる func.sh スクリプトを作成しました。
1. function testfunc ()
2. {
3. echo "--> TESTFUNC CALLED"
4. caller 0
5.
6. # here I mimic that something went wrong
7. echo "now I return a non-zero value"
8. return 1
9. }
次に、main.sh スクリプトを作成しました。
1. #!/bin/bash
2.
3. source 'func.sh'
4. testfunc
5.
6. exit 0
私の目標は、戻り値を正しく管理していないlineno 4 (上記のスクリプト) をキャッチすることです。
そのために私は試しました:
1. #!/bin/bash
2.
3. set -o errexit
4.
5. function exit_handler ()
6. {
7. echo "--> EXIT HANDLER"
8.
9. echo "BACKTRACE IS:"
10. local i=0
11. while caller $i > /dev/null
12. do
13. caller $i
14. let "i=i+1"
15. done
16.
17. echo "PASSED LINENO IS: $1"
18. exit 0
19. }
20. trap 'exit_handler $LINENO' EXIT
21.
22. source 'func.sh'
23. testfunc
24.
25. exit 0
ここでlineno 23をキャッチしたいと思います。
出力は次のとおりです。
--> TESTFUNC CALLED
23 main import.sh
now I return a non-zero value
--> EXIT HANDLER
BACKTRACE IS:
1 main.sh
PASSED LINENO IS: 1
正しい lineno は、関数自体の内部で呼び出し元によって検出されますが、トラップでは検出されません。スクリプトの名前は正しい (main.sh) が、lineno ではありません (22 ではなく 1????)
私も試しました
1. #!/bin/bash
2.
3. function err_handler ()
4. {
5. echo "--> ERR HANDLER"
6.
7. echo "BACKTRACE IS:"
8. local i=0
9. while caller $i > /dev/null
10. do
11. caller $i
12. let "i=i+1"
13. done
14.
15. echo "PASSED LINENO IS: $1"
16. exit 0
17. }
18. trap 'err_handler $LINENO' ERR
19.
20. source 'func.sh'
21. testfunc
22.
23. exit 0
しかし、出力は次のとおりです。
--> TESTFUNC CALLED
21 main import.sh
now I return a non-zero value
--> ERR HANDLER
BACKTRACE IS:
8 main.sh
PASSED LINENO IS: 8
関数自体の内部の呼び出し元はまだ正しいlineno (この場合は 21) を検出していますが、トラップ内の状況はさらに最悪です。これは、 return 1 がある func.sh 内の行である lineno 8 を取得しているためです ... (トラップ内の呼び出し元が行を間違ったスクリプト main.sh に参照している間)。
この時点でアイデアが尽きた…