Ste*_*ige 5 linux bash shell centos7 bash-trap
对于 Bash 程序:
1 #!/bin/bash
2
3 trapinfo()
4 {
5 echo "=== Trap Info: Status=$? LINENO=$@ A=$A"
6 }
7
8 main()
9 {
10 trap 'trapinfo $LINENO -- ${BASH_LINENO[*]}' ERR
11
12 set -e
13 set -E
14 set -o errtrace
15 shopt -s extdebug
16
17 local -g A=1
18
19 # false # If uncommented, LINENO would be 19
20 (exit 73) # LINENO is 9. How can I get 20 instead?
21
22 A=2
23 }
24
25 main
Run Code Online (Sandbox Code Playgroud)
输出:
=== Trap Info: Status=73 LINENO=9 -- 25 0 A=1
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种方法来拥有它,以便以非零状态退出的子shell被捕获trap并显示失败的子shell的行号。在上面的示例中,我正在寻找第 20 行作为结果。我注意到如果错误不在子shell中,我会得到想要的行号(见false上文)。
我尝试将陷阱移动到子外壳之前,以检查行号9是否实际连接到陷阱调用,但我得到了相同的结果。我还尝试将set和shopt条目放入子shell 中——同样没有改变行为。
环境:
是否可以获取返回非零状态的子进程的行号?如果不可能,是否有任何文件可以说明这一点?如果存在解决方案,它应该可以很好地扩展,而无需在代码中进行不必要的修饰。
我向 Bash 电子邮件组help-bash寻求帮助。Eduardo Bustamante 提供了以下两个代码块来指出 Bash 中可能存在的错误,该错误是此处困难的根源。
首先,对问题进行更简单的演示:
1 #!/bin/bash
2 shopt -s extdebug
3 main() {
4 trap 'echo $LINENO' ERR
5 (exit 17)
6 }
7 main
Run Code Online (Sandbox Code Playgroud)
上面的输出为3.
接下来,考虑更改$(...)为`...`:
1 #!/bin/bash
2 shopt -s extdebug
3 main() {
4 trap 'echo $LINENO' ERR
5 `exit 17`
6 }
7 main
Run Code Online (Sandbox Code Playgroud)
上面的输出为5.
现在,我做了自己的测试:
1 #!/bin/bash
2 shopt -s extdebug
3 main() {
4 trap 'echo $LINENO' ERR
5 $(exit 17)
6 }
7 main
Run Code Online (Sandbox Code Playgroud)
这也具有所需的输出5。
因此,这个问题的解决方案似乎是这是 Bash 中的一个错误,解决方法是使用命令替换而不仅仅是 subshell ()。
我再次感谢爱德华多·布斯塔曼特的洞察力。我会等几天看看他是否在这里发布解决方案以接受他的答案;否则,我会将其标记为已接受的答案并向他表示感谢。