Bash 将SIGTERM发送到所有进程
我有一个启动多个进程的bash脚本调用Bash 将SIGTERM发送到所有进程,bash,shell,docker,Bash,Shell,Docker,我有一个启动多个进程的bash脚本调用run.sh #!/bin/bash proc1 & proc2 & proc3 & final # this runs until sigterm 当我执行run.sh并向run.sh发送一个SIGTERM时,我不认为SIGTERM被发送到final,也不认为它被发送到proc1、proc2和proc3。注意,在这个用例中,这是一个docker容器,它运行run.sh,运行docker stop是我试图发送SIGTERM的方式 b
run.sh
#!/bin/bash
proc1 &
proc2 &
proc3 &
final # this runs until sigterm
当我执行run.sh
并向run.sh发送一个SIGTERM时,我不认为SIGTERM被发送到final
,也不认为它被发送到proc1
、proc2
和proc3
。注意,在这个用例中,这是一个docker容器,它运行run.sh
,运行docker stop
是我试图发送SIGTERM的方式
bash脚本向它启动的所有进程发送sigterm的最简单方法是什么?我能想到的唯一方法是用和启动final
,然后在run.sh
中执行while循环
编辑-我尝试过,但似乎不起作用:
在run.sh中
#!/bin/bash
_term() {
echo "Caught SIGTERM signal!"
}
trap _term SIGTERM
echo "hi"
sleep 100000 &
wait $!
运行docker stop时,我从未看到捕获到的SIGTERM信号代码>正确,我会将它们全部收集在一个数组中,然后在完成后向它们中的每一个发送一个信号。我会使用类似于awk'{system(“kill-15”$1)}'
您说过您在Docker容器中运行该脚本。您能否提供有关如何启动容器以及如何调用run.sh
的更多详细信息
当调用docker stop
或容器接收到直接的SIGTERM
时,包含PID 1的进程将接收它。当您的run.sh
创建在后台运行的子进程时,它还必须向它们转发信号
因此,使用&
在bash脚本中创建后台子进程不是一个好方法。使用a将是一种很好的做法,因为它可以正确地处理信号并将其转发给其子进程,而无需进一步编写脚本
此外,supervisord
不应作为shell子进程本身启动。如果在Dockerfile
中指定此作为容器命令,则会发生这种情况:
CMD /usr/bin/supervisord
相反,它应该看起来像:
CMD ["/usr/bin/supervisord"]
这样,主管将成为具有PID 1的根进程,并将正确接收所有信号并将其重定向到其子进程。使用作业-p
获取任何后台作业的进程ID,然后将其传递给kill
trap 'kill $(jobs -p)' TERM
proc1 &
proc2 &
proc3 &
wait
所以my run.sh是为docker容器运行的CMD。但是我很困惑-为什么不使用bash on run.sh工作来捕获信号(仅供参考,我只是尝试了,但没有),因为您将明确需要使用trap
s,如前所述。此外,我已经验证了我的run.sh从PID 1I开始,我不会花太多时间让脚本工作。在Docker环境中,这通常是一种不好的做法,而且很难像您刚刚经历的那样运行。每个容器只能使用一个进程,或者使用如上所述的主管。但请看我的最新示例。这不应该起作用吗?您需要将\u term
函数名作为字符串传递,例如:trap'\u term'SIGINT
@h3nrik我试过了'\u term',仍然不起作用您的脚本在睡眠
退出后才能运行处理程序,因为它不会被中断。使用sleep 100000&
在后台运行它;然后执行wait
命令,可以中断该命令以运行hander。顺便说一句,$代码>在脚本中没有很好的定义,因为您还没有运行任何后台命令。@h3nrik\u term
是一个字符串。引号只是保护任何特殊字符不受shell解释的影响;他们没有定义字符串。@chepner我修改了代码。它仍然不输出捕获的SIGTERM信号不要使用kill-9
。这是用来杀死有缺陷的程序的,因为它不允许进程在自己之后清理。在这种情况下,sigterm或sigint可能更合适。当然,除非它们不是行为良好的进程,否则sigkill就是问题所在……因为它不能被忽略。