如何执行一个函数返回一个非零值时,你得到原调用LINENO [英] how to get the original caller lineno when executing a function returning a non-zero value

查看:202
本文介绍了如何执行一个函数返回一个非零值时,你得到原调用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

我跟着的建议<一href=\"http://superuser.com/questions/175799/does-bash-have-a-hook-that-is-run-before-executing-a-command\">this以超级用户的问题。结果
基本上我执行任何命令之前的函数(preexec),我保存了来电者的信息。当错误发生时我看了过去来电者的信息,如果我收到的1出口陷阱LINENO(这永远是错的,因为任何脚本的第一行应该是#!/斌/ 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天全站免登陆