sli*_*eed 27 shell bash kill signals job-control
我正在尝试设置一个 shell 脚本,以便它运行后台进程,当我Ctrlc使用 shell 脚本时,它会杀死孩子,然后退出。
我设法想出的最好的就是这个。似乎kill 0 -INT在等待发生之前也杀死了脚本,所以 shell 脚本在孩子们完成之前就死了。
关于如何让这个 shell 脚本在发送后等待孩子们死亡的任何想法INT?
#!/bin/bash
trap 'killall' INT
killall() {
echo "**** Shutting down... ****"
kill 0 -INT
wait # Why doesn't this wait??
echo DONE
}
process1 &
process2 &
process3 &
cat # wait forever
Run Code Online (Sandbox Code Playgroud)
Mik*_*kel 23
你的kill命令是倒退的。
像许多 UNIX 命令一样,以减号开头的选项必须排在其他参数之前。
如果你写
kill -INT 0
Run Code Online (Sandbox Code Playgroud)
它将-INT视为一个选项,并发SIGINT送到0(0是一个特殊数字,表示当前进程组中的所有进程)。
但是如果你写
kill 0 -INT
Run Code Online (Sandbox Code Playgroud)
它看到0,决定没有更多选项,因此SIGTERM默认使用。并将该当前进程组,因为如果你做了同样的
kill -TERM 0 -INT
Run Code Online (Sandbox Code Playgroud)
(它也会尝试发送SIGTERM到-INT,这会导致语法错误,但它首先发送SIGTERM到0,并且永远不会到达那么远。)
因此,您的主脚本SIGTERM在运行wait和echo DONE.
添加
trap 'echo got SIGTERM' TERM
Run Code Online (Sandbox Code Playgroud)
在顶部,就在之后
trap 'killall' INT
Run Code Online (Sandbox Code Playgroud)
并再次运行以证明这一点。
正如 Stephane Chazelas 指出的那样,默认情况下,您的背景孩子(process1等)将被忽略SIGINT。
无论如何,我认为发送SIGTERM会更有意义。
最后,我不确定是否kill -process group保证先给孩子们。在关闭时忽略信号可能是个好主意。
所以试试这个:
#!/bin/bash
trap 'killall' INT
killall() {
trap '' INT TERM # ignore INT and TERM while shutting down
echo "**** Shutting down... ****" # added double quotes
kill -TERM 0 # fixed order, send TERM not INT
wait
echo DONE
}
./process1 &
./process2 &
./process3 &
cat # wait forever
Run Code Online (Sandbox Code Playgroud)
Sté*_*las 10
不幸的是,在后台启动的命令由 shell 设置为忽略 SIGINT,更糟糕的是,它们无法使用trap. 否则,你所要做的就是
(trap - INT; exec process1) &
(trap - INT; exec process2) &
trap '' INT
wait
Run Code Online (Sandbox Code Playgroud)
因为 process1 和 process2 会在您按下 Ctrl-C 时获得 SIGINT,因为它们属于同一进程组,即终端的前台进程组。
上面的代码将与 pdksh 和 zsh 一起使用,在这方面不符合 POSIX。
对于其他 shell,您必须使用其他东西来恢复 SIGINT 的默认处理程序,例如:
perl -e '$SIG{INT}=DEFAULT; exec "process1"' &
Run Code Online (Sandbox Code Playgroud)
或使用不同的信号,如 SIGTERM。
| 归档时间: |
|
| 查看次数: |
34044 次 |
| 最近记录: |