SIGALRM等待子shell进程?

时间:2013-06-21 11:02:40

标签: shell signals

以下是意外情况:在以下脚本中,SIGALRM未在预期时间调用函数alarm()

#!/bin/sh -x

alarm() {
  echo "alarmed!!!"
}

trap alarm 14
OUTER=$(exec sh -c 'echo $PPID')

#for arg in `ls $0`; do
ls $0 | while read arg; do
  INNER=$(exec sh -c 'echo $PPID')

  # child A, the timer
  sleep 1 && kill -s 14 $$ &

  # child B, some other scripts
  sleep 60 &

  wait $!
done

期望:  1秒后,应调用函数alarm()

实际上:  调用alarm()直到60秒,或者当我们点击 Ctrl + C

我们在脚本中知道,$$实际上表示OUTER进程,所以我想我们应该看到1秒后打印到屏幕上的字符串。但是,直到孩子B退出,我们才会看到alarm()被调用。

当我们对trap行进行评论时,整个程序将在1秒后终止。所以...我想至少会收到SIGALRM,但为什么不调用行动呢?

而且,作为一个附带问题,SIGALRM的默认行为是终止吗?从here我被告知默认情况下会被忽略,为什么OUTER在收到后会退出?

1 个答案:

答案 0 :(得分:3)

来自bash手册页:

如果bash正在等待命令完成并收到已设置陷阱的信号,则陷阱将        在命令完成之前不执行。当bash通过wait等待异步命令时        内置,接收已设置陷阱的信号将导致等待内置立即返回        退出状态大于128,紧接着执行陷阱。

您的原始脚本位于第一个方案中。子shell(while读取循环)已调用wait,但顶级脚本只是等待子shell,因此当它接收到信号时,在子shell完成之前不会执行陷阱。如果您使用kill -s 14 $INNER将信号发送到子shell,则会得到您期望的行为。