【问题标题】:Simultaneously watch for signals and process exit in Bourne shell在 Bourne shell 中同时观察信号和进程退出
【发布时间】:2012-07-20 20:53:36
【问题描述】:

我有一个想要监视另一个程序的 Bourne shell (/bin/sh) 脚本(用于可移植性)。它应该启动另一个程序,然后等待它退出。当第二个程序退出时,它会做一些最后的工作并自行退出。问题是脚本还需要响应信号(例如 USR2)并在这些信号出现时做一些工作。

我的幼稚实现是:

#! /bin/sh
echo $$
trap 'echo Respond to USR2' USR2
/bin/sleep 120 &
pid=$!
wait $pid
echo $pid exited with $?
echo Doing final cleanup

这不起作用。如果我发送 shell SIGUSR2,陷阱会按预期触发,但等待也会结束,返回 140。 /bin/sleep 继续其愉快的方式。典型输出:

28849
Respond to USR2
28850 exited with 140
Doing final cleanup

这种行为在 dash 和 bash 之间是一致的,我可以方便地访问这两个 Bourne shell 衍生物。

我目前的工作是旋转循环等待子 PID 消失,用 kill 进行探测。自旋循环似乎很浪费,如果 PID 被快速重用,它会扩大我的脚本可能错误地等待错误进程的窗口。

#! /bin/sh
echo $$
trap 'echo Respond to USR2' USR2
/bin/sleep 15 &
pid=$!
while /bin/kill -0 $pid 2> /dev/null; do
    echo waiting...
    sleep 2
done
echo Doing final cleanup

考虑到我的目标是同时等待另一个进程退出并能够响应信号,是否有更好的解决方案?

【问题讨论】:

  • 一个 posix 兼容的系统总是安装了 c98(或 cc)... 有一点,一个“脚本”会吐出一个 C 文件,编译它,然后调用它成为最简单的可移植方式做事!不过,我也想看看是否有“适当”的解决方案。
  • 一个未说明的目标是保持简单,因为它也将成为其他人设计的模板。所以我有兴趣尽量减少所涉及的聪明人的数量。可能需要一定的聪明才智,但我希望不是。如果事情不成功,我会退回到 Perl,我可以合理地依赖它存在于我真正关心的系统上。
  • 我低估了我的问题。我确实需要知道我的第二个程序是如何通过退出或信号退出的。外壳不会帮助我。 (感谢 William Pursell 指出这一点。)因此,在这种情况下,出于我自己的需要,这取决于 Perl。我将标记最能回答我最初问题的答案,希望它对可能能够接受该约束的其他人有用。

标签: signals sh wait shell-trap


【解决方案1】:

你可以这样做:

while wait $pid; test $? -gt 128; do
    kill -0 $pid 2> /dev/null || break;
done

但请注意 sh 标准中的以下内容:

如果等待的退出状态大于 128,则应用程序无法知道等待的进程是以该值退出还是被信号杀死。由于大多数实用程序以较小的值退出,因此很少有任何歧义。即使在模棱两可的情况下,大多数应用程序只需要知道异步作业失败即可;不管它是否检测到错误并失败或被杀死并且没有正常完成其工作。

在这种情况下,歧义略有不同。你不知道wait是被信号打断了还是孩子被信号终止了。

【讨论】:

  • 被接受为我在实践中能做的最好的事情。对于我自己的需要,可惜不够好;我跳到了另一种具有更好流程管理的语言。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-22
  • 1970-01-01
  • 1970-01-01
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 2015-10-20
相关资源
最近更新 更多