我有一个备份守护进程运行在我服务器上的程序每隔几天就会崩溃一次。我不知道为什么。从长远来看,我想找出原因并修复它,但同时我希望 systemd 在崩溃时重新启动它。
它有一个旧式的 SysV 初始化脚本,由 systemd-sysv-generator 拾取。显然,当它崩溃时,它会以零(“成功”)退出代码结束。为了尝试让它在这些崩溃后重新启动,我放入了一个override.conf
:
~$ cat /etc/systemd/system/crashplan.service.d/override.conf
[Service]
Restart=always
systemd 似乎确实注意到了这一点:
roberts:~$ sudo systemctl show crashplan.service | grep Restart
Restart=always
RestartUSec=100ms
尽管如此,几天后当我检查时,我发现:
roberts:~$ sudo systemctl status crashplan.service
● crashplan.service - LSB: CrashPlan Engine
Loaded: loaded (/etc/init.d/crashplan; bad; vendor preset: enabled)
Drop-In: /etc/systemd/system/crashplan.service.d
└─override.conf
Active: active (exited) since Thu 2017-01-05 00:33:50 PST; 5 days ago
Docs: man:systemd-sysv-generator(8)
Jan 05 00:33:50 roberts systemd[1]: Stopped LSB: CrashPlan Engine.
Jan 05 00:33:50 roberts systemd[1]: Starting LSB: CrashPlan Engine...
Jan 05 00:33:50 roberts crashplan[25491]: Starting CrashPlan Engine ... Using standard startup
Jan 05 00:33:50 roberts crashplan[25491]: OK
Jan 05 00:33:50 roberts systemd[1]: Started LSB: CrashPlan Engine.
那么... systemd 似乎认为它没有运行,这很酷吗?没有任何日志表明它甚至试图重新启动它?我甚至不知道如何判断它何时崩溃。这是怎么回事?
答案1
当 init.d 脚本没有指定 PID 文件,其自动生成单元具有RemainAfterExit=yes
在大多数情况下,此类脚本代表没有长时间运行进程的一次性任务,因此此选项会使此类单元即使在进程退出后仍显示为“活动”。
这允许管理员手动“停止”此类单元(例如“启动”/etc/init.d/iptables 加载防火墙规则,然后“停止”它会刷新它们)。但是,由于该单元始终处于“活动”状态,这意味着重启逻辑永远不会触发。(毕竟,是无需重新启动。
这里的解决方案是为 CrashPlan 编写一个本机 systemd .service 文件 - 或者至少让守护进程生成一个 pidfile 并# pidfile: /run/...
相应地添加到 initscript 中。
...或者,首先运行systemctl cat crashplan.service
查看完整的单元内容,然后手动撤消所有错误的参数:RemainAfterExit、GuessMainPID 等等。
另请参阅提交f87883039并归档sysv-generator.c 第 197 行。