Bash 如何向孤立的背景进程发送信号?

Bash 如何向孤立的背景进程发送信号?,bash,unix,signals,tcl,orphan,Bash,Unix,Signals,Tcl,Orphan,我正在后台从tcl脚本执行shell脚本。tcl脚本在一段时间后结束执行。此时,我假设后台shell脚本变成孤立脚本,并被init采用 set res [catch { exec sudo $script &}] 现在的问题是我无法向我的(孤立的)背景脚本发送信号。但是为什么呢?好的,它现在属于init,但为什么我不能发出信号呢。只有sigkill似乎可以工作,这就终止了它-我需要触发我为处理SIGUSR2而编写的信号处理程序 trap 'process' SIGUSR2 为什么我不

我正在后台从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 -c '(trap foo SIGUSR2;foo(){ echo test; };while true; do echo -n .;sleep 1;done) & echo $!'; read
它将派生一个后台进程,只运行并输出一些点。它还将输出过程的PID,您可以使用该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启动后台进程,都应该没有区别。如果它运行,您可以向它发送一个信号,如果有处理程序,它将被调用


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

它正在等待睡眠完成,但我正在将睡眠的pid写入一个文件,在信号处理程序中,我正在读取该pid并杀死它,然后调用我的函数。奇怪的是,当背景脚本不是孤立脚本时,这种方法可以正常工作。@egorulz Tcl确实不会干扰子进程的信号处理;米查斯所写的一针见血。我认为我们需要问题脚本的更多细节来解决这个谜团(例如,您可能以某种方式让脚本在子进程中进行等待,或者在错误的进程中设置信号处理程序)。这似乎是您代码中的一个问题。尽量减少你的代码,省去所有不一定要重现问题的东西。要么你自己发现问题,要么你最终得到一小段应该添加到问题中的代码。是的,我确实最小化了脚本。这个问题仍然在发生——然后我决定直接给睡眠发信号,而不是发信号给我的脚本,脚本捕捉到这个信号就会杀死睡眠。这解决了问题。但我想知道为什么。