当想要及时处理信号时,在后台休眠然后等待是有意义的。
当 bash 在前台执行外部命令时,它会
在前台进程之前不处理收到的任何信号
终止
(详细解释here http://mywiki.wooledge.org/SignalTrap#When_is_the_signal_handled.3F).
虽然第二个示例实现了信号处理程序,但对于第一个示例,睡眠是否在前台执行没有区别。没有陷阱,信号不会传播到nginx
过程。
为了使其响应SIGTERM
信号,入口点应该是这样的:
/bin/sh -c 'nginx -g \"daemon off;\" & trap exit TERM; while :; do sleep 6h & wait $${!}; nginx -s reload; done'
要测试它:
docker run --name test --rm --entrypoint="/bin/sh" nginx -c 'nginx -g "daemon off;" & trap exit TERM; while :; do sleep 20 & wait ${!}; echo running; done'
停止容器
docker stop test
或发送TERM
信号 (docker stop
发送一个TERM
其次是KILL
如果主进程没有退出)
docker kill --signal=SIGTERM test
通过执行此操作,脚本会立即退出。现在如果我们删除wait ${!}
陷阱被执行时sleep
结束。所有这些也适用于第二个示例。
注意:在这两种情况下,目的是每 12 小时检查一次证书更新,并每 6 小时重新加载配置,如guide https://medium.com/@pentacent/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71这两个命令就可以很好地做到这一点。恕我直言,第一个示例中的额外等待只是开发人员的疏忽。
EDITED:
上面的合理化旨在给出背景睡眠背后的可能原因,但可能会造成一些混乱。
(有相关帖子为什么在 docker 后台使用“守护进程关闭”的 nginx? https://stackoverflow.com/q/57554703/8482479).
虽然上面答案中建议的命令比问题中的命令有所改进,但它仍然存在缺陷,因为正如链接帖子中提到的,nginx
服务器应该是主进程而不是子进程。这可以使用以下方法轻松实现exec
系统调用。脚本变为:
'while :; do sleep 6h; nginx -s reload; done & exec nginx -g "daemon off;"'
(更多信息请参见部分将应用程序配置为 PID 1 in Docker 最佳实践 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
恕我直言,这要好得多,因为不仅nginx
受监视,但它也处理信号。配置重新加载(nginx -s reload
),例如,也可以通过简单地发送HUP
向 docker 容器发送信号(参见控制 Nginx http://nginx.org/en/docs/control.html).