【问题标题】:How to signal orphaned background process?如何向孤立的后台进程发出信号?
【发布时间】:2014-02-01 18:58:47
【问题描述】:

我正在后台从我的 tcl 脚本执行一个 shell 脚本。 tcl 脚本在一段时间后结束执行。在这一点上,我假设后台 shell 脚本成为孤立的并被 init 采用。

set res [catch { exec sudo $script &}]

现在的问题是我无法向我的(孤立的)后台脚本发出信号。但为什么?好的,它现在属于 init 但为什么我不能发出信号。只有 sigkill 似乎有效并且杀死了它 - 我需要触发我编写的信号处理程序来处理 SIGUSR2

trap 'process' SIGUSR2

为什么我不能向我的孤立后台进程发出信号?有没有办法做到这一点?或者有什么解决办法?

编辑:不涉及睡眠时似乎工作正常。请参阅下面的示例代码:

trap 'kill `cat /var/run/sleep.pid`; foo' SIGUSR2;

foo(){ echo test; }

while true; do
  echo -n .
  sleep 100 &
  echo ${!} > /var/run/sleep.pid
  wait ${!}
done

在没有孤立的情况下工作正常 - 但在孤立进程的情况下,我认为问题是真正的睡眠 pid 被覆盖,当陷阱到达时我无法杀死它。

【问题讨论】:

    标签: bash unix signals tcl orphan


    【解决方案1】:

    让我们像这样运行一个小脚本:

    bash -c '(trap foo SIGUSR2;foo(){ echo test; };while true; do echo -n .;sleep 1;done) & echo $!'; read
    

    它将派生一个后台进程,该进程仅运行并输出一些点。它还将输出进程的PID,您可以使用它来检查和发出信号。

    $ ps -f 19489
    UID        PID  PPID  C STIME TTY      STAT   TIME CMD
    michas   19489     1  0 23:45 pts/8    S      0:00 bash -c (trap foo SIGUS...
    

    因为在后台运行命令后,forking shell 直接死亡,所以进程现在归 init (PPID=1) 所有。

    现在您可以向进程发出信号以调用处理程序:

    kill -USR2 19489
    

    如果这样做,您会注意到终端上的“测试”输出打印了点。

    无论是从 shell 还是 tcl 启动后台进程,应该没有区别。如果它运行,你可以向它发送一个信号,如果有一个处理程序,它将被调用。

    如果它真的不响应信号,它可能会被阻塞,等待某些东西。例如在sleep 或等待一些 IO。

    【讨论】:

    • 它正在等待睡眠完成,但我正在将睡眠的 pid 写入文件,并且在信号处理程序上,我正在读取这个 pid 并杀死它,然后调用我的函数。奇怪的是,当后台脚本不是孤立的时,这工作得很好。
    • @egorulz Tcl 确实不会干扰子进程的信号处理; michas 写的很到位。我认为我们需要问题脚本的更多细节来解决这个谜团(例如,您可能以某种方式让脚本在子进程中进行等待或在错误的进程中设置信号处理程序)。
    • 这似乎是您的代码中的一个问题。尽量减少你的代码,忽略所有不是重现问题所必需的东西。要么您自己发现问题,要么最终得到一小段代码,您应该将其添加到您的问题中。
    • 是的,我确实最小化了脚本。问题仍然存在 - 然后我决定直接发出睡眠信号,而不是发出我的脚本,然后捕获信号杀死睡眠。这解决了问题。但我不知道为什么。
    猜你喜欢
    • 1970-01-01
    • 2012-08-09
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多