bash - 为什么在docker的后台使用带有“守护进程关闭”的nginx?
问题描述
这一切都始于这篇关于在 docker 中设置 nginx 和 certbot 的文章。在手册的最后,作者使用以下命令为 nginx 自动更新证书:
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
我不是唯一一个不理解这部分的人,所以有一个关于 SO 的问题:为什么要在 bash 中睡眠和等待?
给出的答案是原始命令并不完美,这里是更正的版本:
/bin/sh -c 'nginx -g \"daemon off;\" & trap exit TERM; while :; do sleep 6h & wait $${!}; nginx -s reload; done'
但是在这个命令中,我看到了nginx -g \"daemon off;\" &
为什么我们首先将 nginx 放在前台,然后将其填充到后台?有什么影响,为什么不首先在后台启动 nginx?
另一个问题:据我了解,while
与原始命令不同,循环停留在 docker 的前台。但是如果nginx如果是后台,是不是就意味着如果死掉了,docker就不管了?在前台while
仍然工作,没问题。
最后一个问题:为什么在这个命令中有时我们会看到$${!}
,有时会看到${!}
. ${!}
来自同一个 SO 问题的示例:
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'
我知道这是一个字符转义,但我不知道这种情况的规则。
解决方案
但是在这个命令中我看到 nginx -g \"daemon off;\" & 为什么我们先把 nginx 放在前台然后把它塞进后台?有什么影响,为什么不首先在后台启动 nginx?
原因主要是为了突出差异,没有任何影响。该命令等效于:
"/bin/sh -c 'nginx; trap exit TERM; while :; do sleep 6h & wait $${!}; nginx -s reload; done'
另一个问题:据我了解,与原始命令不同,while 循环停留在 docker 的前台。但是如果nginx如果是后台,是不是就意味着如果死掉了,docker就不管了?在前台仍然工作,没问题。
该命令基本上创建了三个进程:shell 进程 ( /bin/sh
)sleep 6H
和nginx
服务器。第四个进程 ( nginx -s reload
) 每 6 小时派生一次。Docker 始终监视PID 1
在这种情况下是 shell ( /bin/sh
) 的进程。如果外壳死了,容器就会退出。如果作为nginx
shell 进程的子进程的服务器在 docker 中死掉,确实不在乎。
“更正”的版本没有解决这些问题。它与原始问题具有相同的问题。SO问题的答案仅强调除非您想及时处理信号,否则不需要sleep
and 。wait
代表着:
"/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx ..."
与以下内容完全相同:
"/bin/sh -c 'while :; do sleep 6h; nginx ..."
总之,一个正确的实现将nginx
作为主进程(PID 1
)和另一个在后台运行的进程每 6 小时唤醒一次,以向服务器发出重新加载配置的信号。原始命令和更正后的命令都不能正确实现所有这些。
要解决前面提到的问题,命令应该是这样的:
'while :; do sleep 6h; nginx -s reload; done & exec nginx -g "daemon off;"'
系统调用将 shell 进程的exec
内容替换为将主进程置于前台的nginx
服务器。nginx
现在所有信号都正确传播到服务器(另请参阅控制 nginx)。
注意:此解决方案仍有缺陷。不监视 shell 进程(while 循环)。如果出于任何原因此过程退出,docker 唯一要做的就是发送警报。
希望这能有所启发。
推荐阅读
- javascript - 根据变量值防止点击html元素
- kubernetes - cert-manager:让我们加密拒绝 ACME 帐户
- ios - UserDefaults.standard.set() 仅在 watchOS 上不起作用
- pytorch - 为什么 timm 视觉变压器位置嵌入初始化为零?
- android - 有没有办法让 actionBar 后退按钮用 putExtra 重新发送意图?
- arrays - 使用 For each Statement 循环遍历 VBA Excel 中的多维数组 - 仅第一维
- react-native - React native reducer:如何更新数组中的对象值
- r - 行名称列并修改 R 中的日期
- javascript - 制作一个按钮来移动一个对象
- android - Paging 3 如何处理数据并与房间交互