运维笔记

systemd-journald的SIGPIPE信号BUG

Einic Yeo · 3月24日 · 2019年 · · ·

在重启systemd-journald后, 意外的发现, 本台服务器上的其他由 systemd 托管的部分服务, 却意外被 stop 掉了, 由于大部分服务的 unit 文件中都配置了 Restart 规则为 on-failure. 所以如果是异常的退出, 这些服务应该会重启才对. 很明显, 这些服务是被”正常”关闭的.

在查看被 stop 的应用状态时, 发现了以下线索

$ sudo systemctl status kube-apiserver
 ……
 Active: inactive (dead) since Thu 2018-11-22 13:53:46 CST; 25min ago
 Main PID: 90457 (code=killed, signal=PIPE)
 ……

code=killed, signal=PIPE 这些信息告诉我们, 这个进程是被SIGPIPE信号关闭的. 在网上查阅资料时, 发现 github 中大量的项目 issue 下都有相版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!关的问题. 而问题的矛头都指向了systemd-journald这个服务的重启事件!

问题的原因在于: systemd-journald这个服务重启的时候, 会给所有版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!的进程发送SIGPIPE信号, 而在默认的 systemd 定义中, SIGPIPE 信号属于正常退出的范围. 所以即使 unit 文件配置了Restart on-failure也不会被重启

该问题是 systemd 的已知 BUG 之一. 规避该问题的方式有很多种, 其中以下这种方式并没有生效

$ systemctl show kube-apiserver | grep PIPE
 IgnoreSIGPIPE=yes

默认情况下版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!, IgnoreSIGPIPE=yes是配置好的, 理论上会忽略掉接收到的SIGPIPE信号, 但实际情况表明, 并没有被忽略

解决方案

在 systemd 的 unit 文件中的 Restart 策略设置为 Always, 这样即使是正常的关闭, 也会重启服务
在 systemd 的 unit 文件中配置 RestartForceExitStatus=SIGPIPE 指定收到这个信号时, 强制重启服务
坏消息:

RestartForceExitStatus 的配置在 systemd 215中才被加入, 对于使用之前版本的情况来说, 并没有什么帮助, 可能Always是唯一的选择

病友:

https://github.com/influxdata/influxdb/issues/7040
https://github.com/syncthing/syncthing/issues/2350
https://github.com/moby/moby/is版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!sues/7087
https://github.com/systemd/systemd/issues/6620

参考文档

https://bugs.freedesktop.org/show_bug.cgi?id=849版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!23
http://www.jinbuguo.com/systemd/systemd.service.html

0 条回应