我有一个bash脚本进程,它在某些时候同步执行一个长时间运行的子进程.在该子进程的运行期间,信号被直接发送到bash脚本进程,请求脚本终止.有没有办法拦截该信号,终止子进程,然后退出bash进程?
显然,bash的信号处理从不中断同步调用?
我无法控制终止信号被发送到bash进程的事实.虽然如果信号可以传播到子进程,那也可以解决我的问题.
提前谢谢,布鲁斯
请参阅bash的手册页,SIGNALS一章:
如果bash正在等待命令完成并收到已设置陷阱的信号,则在命令完成之前不会执行该陷阱.当bash通过wait builtin等待异步命令时,接收到已设置陷阱的信号将导致wait builtin立即返回,退出状态大于128,之后立即执行陷阱.
因此,异步运行外部程序并使用wait.使用$!杀死它.
是的,可以用命令拦截信号trap。请参阅下面的示例:
#!/bin/bash
function wrap {
local flag=0
trap "flag=1" SIGINT SIGTERM
xeyes &
subppid=$!
while :
do
if [ $flag -ne 0 ] ; then
kill $subppid
break
fi
sleep 1
done
}
flag=0
trap "flag=1" SIGINT SIGTERM
wrap &
wrappid=$!
while : # This is the same as "while true".
do
if [ $flag -ne 0 ] ; then
kill $wrappid
break
fi
sleep 1 # This script is not really doing anything.
done
echo 'end'
Run Code Online (Sandbox Code Playgroud)
基本上trap所做的就是执行“”之间的命令。所以这里的main函数就在下面的while循环中。在每次迭代中,脚本都会检查该标志是否已设置,如果没有,它会休眠一秒钟。在此之前,我们通过 记住了子进程的pid $!。SIGINT当或被捕获时,陷阱会发出命令SIGTERM(其他信号请参阅kill手册)。
包装函数的作用与主函数相同。此外,它还调用实际subprocess函数(在本例中,子进程是xeyes)。当包装函数SIGTERM从主函数接收到信号时(主函数也捕获了其中一个信号),包装函数可以在实际杀死子进程之前清理一些东西。之后,它脱离 while 循环并退出包装函数。然后 main 函数也会中断并打印'end'。
编辑:希望我正确理解这一点,你被迫执行xeyes &. 那么步骤如下(在终端中):
xeyes &
subpid=$!
trap "kill $subpid && exit " SIGINT SIGTERM
.... other stuff
.... more stuff
^C #TERMINATE - this firstly kills xeyes and then exits the terminal
Run Code Online (Sandbox Code Playgroud)