【发布时间】:2019-04-10 17:39:04
【问题描述】:
我们有一个包装脚本,它在后台启动 DelayedJob 工作者。此脚本等到 DelayedJob 工作程序完成后才退出。包装脚本是 Docker 容器的主要入口点,并设置了 DJ 工作者运行所需的一些环境。
我们注意到,当发出 Docker stop 时,Docker 容器应该等到 DJ 工作者正常退出(或直到最大超时),但这并没有发生。容器立即退出。
向容器发出 Docker 停止调用会向主进程(包装脚本)发送 SIGTERM。在包装脚本中,我们捕获 SIGTERM 并将信号传递给 DJ 工作进程。
这仍然不起作用。我使用简单的 Bash 脚本创建了一个测试用例来说明问题。
脚本 p1:
#!/bin/bash
echo "P1: starting p1 and running p2 in bg"
exit_script() {
echo "P1: Caught sigterm in p1, sending TERM to p2"
kill -TERM $child
}
trap exit_script SIGINT SIGTERM
./p2 &
child=$!
echo "P1: waiting for p2 ($child)"
wait $child
echo "P1: Finished waiting for p2, exiting p1"
脚本 p2:
#!/bin/bash
echo "P2: starting p2"
exit_script() {
echo "P2: Caught sigterm"
NEXT_WAIT_TIME=0
until [ $NEXT_WAIT_TIME -eq 10 ]; do
echo "P2: EXIT_SCRIPT loop $NEXT_WAIT_TIME"
sleep $(( NEXT_WAIT_TIME++ ))
done
exit
}
trap exit_script SIGINT SIGTERM
echo "P2: Sleeping for a while"
NEXT_WAIT_TIME=0
until [ $NEXT_WAIT_TIME -eq 10 ]; do
echo "P2: Main Loop $NEXT_WAIT_TIME"
sleep $(( NEXT_WAIT_TIME++ ))
done
echo "P2: Finished sleeping in p2"
输出:
MBP:$ ./p1
P1: starting p1 and running p2 in bg
P1: waiting for p2 (74039)
P2: starting p2
P2: Sleeping for a while
P2: Main Loop 0
P2: Main Loop 1
P2: Main Loop 2
P2: Main Loop 3
P2: Main Loop 4
P1: Caught sigterm in p1, sending TERM to p2
P1: Finished waiting for p2, exiting p1
MBP:$ P2: Caught sigterm
P2: EXIT_SCRIPT loop 0
P2: EXIT_SCRIPT loop 1
P2: EXIT_SCRIPT loop 2
P2: EXIT_SCRIPT loop 3
P2: EXIT_SCRIPT loop 4
P2: EXIT_SCRIPT loop 5
P2: EXIT_SCRIPT loop 6
P2: EXIT_SCRIPT loop 7
P2: EXIT_SCRIPT loop 8
P2: EXIT_SCRIPT loop 9
如您所见,p1 脚本调用wait 之后的行在捕获信号时调用的exit_script 函数中的代码之前执行。
解决方案是将wait 替换为检查子PID 是否存在的超时循环,但为什么wait 不能按预期工作? wait的用法有误吗?
【问题讨论】:
标签: linux bash docker delayed-job