我正在从我的tcl脚本执行后台shell脚本。 tcl脚本在一段时间后结束执行。此时我假设后台shell脚本变为orphan并被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被覆盖,当陷阱到来时我无法杀死它。
答案 0 :(得分: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...
因为在后台运行命令后,forking shell直接死亡,所以该进程现在由init(PPID = 1)拥有。
现在您可以通知进程调用处理程序:
kill -USR2 19489
如果这样做,您会注意到终端上的“测试”输出打印点。
无论是从shell还是tcl启动后台进程都应该没有区别。如果它运行,你可以发送一个信号,如果有一个处理程序,它将被调用。
如果它真的没有回应信号它可能被阻止,等待某事。例如,在sleep
或等待某些IO。