如何捕获正在执行可能抛出文件的shell脚本的信号?

时间:2013-08-21 18:19:42

标签: c linux shell signals

我有一个shell脚本,它正在执行一个基本上是C程序的程序fuseIO

这个想法是,这个可执行文件fuseIO可能会在SIGABRT内部调用abort( ),在这种情况下,while循环应该退出。

如何做到这一点?

i=0
while [ $i != 10 ]
do
   echo "************ Iteration: $i *********\n" 2>&1 |tee -a log.txt
   ./fuseIO 2>&1 | tee -a log.txt // This may throw SIGABRT
   i=`expr $i + 1`
   sleep 1
done

1 个答案:

答案 0 :(得分:2)

在某种程度上,请参阅Exit status codes greater than — possible? WIFSIGNALED的内容告诉您已发出进程信号,但是shell编码存在问题,并且通过将发出信号的退出状态编码为128 +信号来实现数字(HUP为129,INT为130等)。要演示shell和信号退出状态:

$ cat killme.sh
#!/bin/bash
kill ${1:-"-INT"} $$
$ ./killme.sh -HUP; echo $?
Hangup: 1
129
$ ./killme.sh -TERM; echo $?
Terminated: 15
143
$ ./killme.sh -QUIT; echo $?
0
$ ./killme.sh -PIPE; echo $?
141
$ ulimit -a
core file size          (blocks, -c) 0
...
$

这或多或少证明了我的 + + signum'声明(-QUIT行为是意料之外的,但可以在时尚之后解释 - 它通常会转储核心,但没有因为ulimit已禁用它们。)

bash中,您可以从最近执行的前台管道(可能只包含一个命令)中的进程获取退出状态值列表。通过数组$PIPESTATUS。例如:

$ ./killme.sh | exit 31

$ echo ${PIPESTATUS[*]}
130 31
$

这对应于SIGINT(2)的130退出状态加上显式退出状态31.注意符号:${PIPESTATUS[0]}带有索引周围的大括号。双引号和内容的作用类似$* vs $@ vs "$*" vs "$@",以获取数组中的所有值。

应用于您的两部分管道,您应该能够测试:

if [[ ${PIPESTATUS[0]} == 134 ]]
then : FuseIO crash with SIGABRT
fi

如果没有| tee,您只需测试$?

if [[ $? > 128 && $? < 160 ]]
then : died a signalled death (probably)
else : died an ordinary death
fi

这里的160也是一个明智的猜测;它应该是128 + SIGRTMAX。请注意,如果某个流程执行exit 135,则会将其视为已发出信号(即使它未发出信号)。