$?里面的bash陷阱

时间:2013-07-29 21:00:19

标签: bash signals return-value bash-trap

从bash脚本,我正在尝试处理来自c ++程序的分段错误。我已经读过在trap上使用SIGCHLD可以用于此目的。在陷阱内部,我应该能够测试$?以从程序中获取返回码。例如,请参阅https://unix.stackexchange.com/questions/24307

这对我不起作用,我无法弄明白为什么。

这是脚本:

#! /bin/bash

set -bm

trap 'echo "Trap result code $?"' CHLD

echo "Script: starting program"
./sigsegv
echo "Script: result code from program was $?"

正如您可能猜到的那样,sigsegv程序只会导致段错误:

#include <csignal>
#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    cout << "C++ will now cause a SIGSEGV" << endl;
    raise(SIGSEGV);
    cout << "After signal -- shouldn't get here" << endl;
    return 0;
}

当我运行包装器脚本时,我得到了这个:

$./wrappersimple.sh 
Script: starting program
C++ will now cause a SIGSEGV
Trap result code 0
./wrapper.sh: line 8: 26368 Segmentation fault      (core dumped) ./sigsegv
Script: result code from program was 139

关键部分是Trap result code 0。这就是我期望它说139表示SIGSEGV(SIGSEGV为128基础值+11)。

如果重要,RHEL 6.2,bash 4.1.2(1)-release。

1 个答案:

答案 0 :(得分:4)

我不是肯定的,但我认为在调用$?的处理程序时,shell尚未更新CHLD的值。考虑一下这个脚本:

set -bm

trap 'echo "Trap result code $?"' CHLD

echo "Script: starting program"
(exit 9)
(exit 11)
echo "Script: result code from program was $?"

我用一个模拟seg错误的简单子shell替换你的C ++程序。当我运行它时,CHLD陷阱打印“陷阱结果代码9”,表示陷阱在触发陷阱之前看到命令的退出状态。将第一个子shell调用的值更改为exit会更改陷阱打印的值。


您链接的问题会捕获EXIT伪信号。如果不深入研究bash源代码,我怀疑会发生什么:

  1. 设置CHLD

  2. 的陷阱
  3. 对于每个命令:

    一个。运行命令

    湾执行收到信号的陷阱

    ℃。设置$?

  4. 执行EXIT陷阱,如果有的话

  5. 退出

  6. 在步骤2b中,对应于2a中的命令的$?的值尚不可用。在步骤3中,与脚本关联的$?的值可用,因为它与脚本中执行的最后一个命令的2c值相同。