Systemd中通过ExecReload发送SIGUSR2实现优雅二进制升级的相关疑问
Systemd中通过ExecReload发送SIGUSR2实现优雅二进制升级的相关疑问
嘿,针对你想用systemd的ExecReload配合SIGUSR2实现Coredns优雅二进制升级的疑问,我来逐一给你唠清楚:
1. systemd会知道PID发生变化吗?
默认情况下完全不会。为啥呢?看这几点:
- 你配置了
Type=forking和PIDFile=/tmp/coredns.pid,systemd只会在服务启动那一次读取这个PID文件,之后就死死盯着那个老PID了。 - 当你执行
systemctl reload coredns发送SIGUSR2后,老进程退出,新进程虽然会把自己的PID写入同一个文件,但systemd根本不会主动去重新读这个文件更新跟踪的PID。 - 结果就是,systemd还傻乎乎地认为老PID是服务的主进程,哪怕老进程已经凉透了。
要是想让systemd认出新的PID,你得在ExecReload命令里加几步操作,比如:
ExecReload=/bin/kill -s USR2 $(cat /tmp/coredns.pid); sleep 1; /bin/systemctl daemon-reload; /bin/systemctl reset-failed coredns
不过说实话,这种涉及PID变更的优雅升级,其实更贴合systemctl restart的场景,但常规restart会有 downtime,而你的SIGUSR2是无停机的,所以用ExecReload凑合用也可以,就是得额外处理PID跟踪的问题。
2. 日志和进程监控还能正常工作吗?
如果systemd没识别到新PID,那肯定出问题:
- 进程监控:systemd还盯着老PID,老进程一退出,它可能会觉得服务异常挂了,触发你配置的
Restart策略(如果有的话),搞出不必要的重启;而且新进程不在systemd的监控范围内,之后你执行systemctl stop coredns可能根本停不掉新进程。 - 日志收集:新进程的输出不会被journald捕获(因为它不是systemd启动的子进程),你只能从Coredns自己配置的日志文件里看日志,journalctl里查不到新进程的记录。
要解决这个问题,除了让systemd重新识别新PID,另一种办法是让Coredns在优雅升级时主动通知systemd(比如用sd_notify机制),但得看Coredns支不支持。要是不支持,那就只能靠调整ExecReload的命令,强迫systemd更新跟踪的PID了。
另外提一句:systemd官方对ExecReload的定位是「不改变PID的重载操作」,你的场景其实属于优雅重启(PID会变),所以用ExecReload虽然能触发动作,但其实不符合systemd的设计预期。如果有条件,你可以自定义一个服务动作,或者用专门的优雅升级工具;要是就想坚持用ExecReload,那一定要把PID跟踪的问题处理好。
备注:内容来源于stack exchange,提问作者Kokizzu
相关产品推荐
相关产品推荐

