linux - bash 陷阱 : How to Get Line Number of a Subprocess with Non-Zero Status

标签 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

输出:

=== Trap Info: Status=73 LINENO=9 -- 25 0 A=1

我正在寻找一种方法,以便以非零状态退出的子 shell 被 trap 捕获并显示失败子 shell 的行号。在上面的示例中,我正在寻找 line 20 作为结果。我注意到,如果错误不在子 shell 中,我会得到所需的行号(参见上面的 false)。

我尝试将陷阱移动到子 shell 之前,以检查行号 9 是否实际连接到陷阱调用,但我得到了相同的结果。我还尝试将 setshopt 条目也放入子 shell 中——同样没有任何行为变化。

环境:

  • bash-4.2.46-21.el7_3.x86_64:这是一项要求,但不要求符合 POSIX。我也对以后的 Bash 版本(4.2+)感兴趣。
  • CentOS 7+:虽然主要对 CentOS 感兴趣,但我最终也需要它来部署在 Ubuntu 16.04+ 和 CentOS 6 上的 Bash 脚本。

是否可以获取返回非零状态的子进程的行号?如果不可能,是否有任何相关文件?如果存在解决方案,它应该可以很好地扩展,而不会在代码中进行不必要的修饰。

最佳答案

我问了 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

上面有3的输出。

接下来,考虑将 $(...) 更改为 `...`:

     1  #!/bin/bash
     2  shopt -s extdebug
     3  main() {
     4  trap 'echo $LINENO' ERR
     5  `exit 17`
     6  }
     7  main

上面有5的输出。

现在,我做了自己的测试:

     1  #!/bin/bash
     2  shopt -s extdebug
     3  main() {
     4  trap 'echo $LINENO' ERR
     5  $(exit 17)
     6  }
     7  main

这也有所需的输出 5

因此,这个问题的解决方案似乎是 Bash 中的一个错误,解决方法是使用 command substitution而不仅仅是一个子 shell ()

再次感谢 Eduardo Bustamante 的洞察力。我等几天看看他有没有在这里发布解决方案来接受他的回答;否则,我会将此标记为已接受的答案并感谢他。

关于linux - bash 陷阱 : How to Get Line Number of a Subprocess with Non-Zero Status,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41346907/

相关文章:

c - gcc ld 错误 "libgcov.a(_gcov_merge_add.o) is referenced by DSO"

linux - 如何获取 find 命令的参数并将它们打印出来?

linux - 确定跨 Linux 平台加载哪个共享库的可靠方法是什么?

linux - linux shell 实用程序 pidof 的源代码

linux - 将 shell 脚本转储公开给网络监控工具

linux - 评估文件中的 shell 命令

linux - Cron 作业不会为非 root 用户自动运行

linux - g++ 静态链接到 libstdc++.a 错误

bash - 在 bash 脚本中将未知选项设置为 `s'

windows - Erlang shell 自动完成功能在 Windows 上不起作用