0

我正在从我的 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 被覆盖,当陷阱到达时我无法杀死它。

4

1 回答 1

2

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

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...

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

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

kill -USR2 19489

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

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

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

于 2014-02-01T23:04:16.493 回答