当执行返回非零值的函数时,如何获取原始的调用者lineno [英] how to get the original caller lineno when executing a function returning a non-zero value

查看:174
本文介绍了当执行返回非零值的函数时,如何获取原始的调用者lineno的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经制作了一个func.sh脚本,其中包含:

I've made a func.sh script to be sourced containing:

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脚本

Then I've made a main.sh script

1. #!/bin/bash
2.
3. source 'func.sh'
4. testfunc
5.
6. exit 0

我的目标是抓住lineno 4 (在上面的脚本中),我没有正确地管理返回值。



为此,我尝试:

My goal is to catch lineno 4 (in the above script), where I haven't managed correctly the returning value.

To do that I tried:

 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

输出是:

Here I would like to catch the lineno 23.
The output is:

--> 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(1 ????而不是22)




我也尝试过

The correct lineno is detected by caller inside the function itself, but not in the trap, where the name of the script is correct (main.sh) but not the lineno (1???? instead of 22)

I also tried

 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 ),但陷阱内的情况甚至更糟,因为它获得了lineno 8这是行在func.sh里面有返回1 ...(而陷阱内的调用者将线路指向错误的脚本main.sh)。




此时我用完了想法...

The caller inside the function itself is still detecting the right lineno (21 in this case), but the situation inside the trap is even worst because it's getting the lineno 8 which is the line inside func.sh where there's the return 1 ... (while the caller inside the trap refers the line to the wrong script main.sh).

At this point I ran out of ideas...

推荐答案

我以这种方式解决了:

 1. #!/bin/bash
 2.
 3. set -o errexit
 4. 
 5. function exit_handler ()
 6. {
 7.     local p_lineno="$1"
 8.
 9.     echo "--> ERR HANDLER"
10. 
11.     for (( i=${#g_bash_lineno[@]}-1; i>=0; i-- ))
12.         do
13.         test ${g_bash_lineno[$i]} -ne 1 && break
14.     done    
15.
16.     local g_lineno="${g_bash_lineno[$i]}"
17. 
18.     if test ${p_lineno} -eq 1 && test ${g_lineno} -gt 1
19.         then
20.         local lineno="${g_lineno}"
21.         else
22.         local lineno="${p_lineno}"
23.      fi
24. 
25.      local source="${g_bash_source[-1]}"
26. 
27.      echo "LINENO: ${lineno}"   
28.      echo "FILE: ${source}"
29. 
30.      exit
31. }
32. trap 'exit_handler $LINENO' EXIT 
33.
34. function preexec ()
35. {
36.     local called=$( caller 0 )
37.     local lineno=$( echo "$called" | cut -d " " -f1 )
38.     local source=$( echo "$called" | cut -d " " -f3 )
39. 
40.     if ! eval '[[ ${!g_bash_lineno[@]} ]]' # isset
41.         then
42.             g_bash_lineno=( "$lineno" )
43.         else
44.             g_bash_lineno=( "${g_bash_lineno[@]}" "$lineno" )
45.     fi
46.    
47.     if ! eval '[[ ${!g_bash_source[@]} ]]' # isset
48.         then
49.             g_bash_source=( "$source" )
50.         else
51.             g_bash_source=( "${g_bash_source[@]}" "$source" )
52.     fi
53. }
54. trap 'preexec' DEBUG
55.
56. source 'func.sh'
57. testfunc
58.
59. exit 0



输出将是


The output will be

--> TESTFUNC CALLED
57 main import.sh
now I return a non-zero value
--> ERR HANDLER
LINENO: 57
FILE: main.sh

我跟着此问题的建议在超级用户上。

基本上,我在任何命令之前执行一个函数(preexec),我存储调用者的信息。当发生错误时,如果我在退出陷阱中收到1的lineno(总是错误的,因为任何脚本的第一行都应该是#!/ bin / bash),那么在最后一个调用者处读取信息。

I followed the suggestion of this question on superuser.
Basically I execute a function (preexec) before any command and I store the information of the caller. When an error occurs I read the information over the last caller if I receive a lineno of 1 in the exit trap (which is always wrong, since the first line of any script should be #!/bin/bash)

这篇关于当执行返回非零值的函数时,如何获取原始的调用者lineno的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆