我有一个老式守护进程,我想使用 systemd 来控制它。当它的配置文件发生更改时,需要将其终止并重新启动。换句话说,在编辑配置文件后,systemctl reload MYSERVICE
应该终止该进程并重新启动它。
尝试 1:尝试默认设置。这会告诉 systemd 如何启动守护进程,但不告诉如何重新加载它。
[Service]
ExecStart=/usr/bin/MYSERVICE
Type=simple
结果,start
工作restart
正常,但是reload
出现了以下错误:
# systemctl reload MYSERVICE
Failed to reload MYSERVICE.service: Job type reload is not applicable for unit MYSERVICE.service.
尝试 2:告诉它如何终止该进程。这会终止该进程,但 systemd 不会帮我重新启动它。
[Service]
ExecStart=/usr/bin/MYSERVICE
Type=simple
ExecReload=/bin/kill -HUP $MAINPID
...其次是...
# systemctl daemon-reload
# systemctl reload MYSERVICE
...终止该进程,但不会自动重新启动。
尝试 3:使用 ExecReload 重新启动该进程。此操作失败,原因如下:
ExecReload=/bin/kill -HUP $MAINPID ; /usr/bin/MYSERVICE
...我收到的错误消息...:
# systemctl daemon-reload
# systemctl reload MYSERVICE
Job for MYSERVICE.service failed because the control process exited with error code. See "systemctl status MYSERVICE.service" and "journalctl -xe" for details.
我希望有一个 ReloadType=kill_and_restart 或类似的东西,但没有那么幸运。
如何告诉 systemd 在重新加载时终止并重新启动守护进程?
答案1
答案是“你不需要”!但我们有好消息。
systemd 的理念是,重新加载是可选的,如果没有真正的重新加载功能,则应将其保留为未定义。我将“真正的重新加载功能”定义为不会终止并重新启动服务或使服务更改其 PID 的重新加载。换句话说,systemd 只想反映现有的功能。
相反,您应该使用systemctl reload-or-restart
如果存在则重新加载,如果不存在则重新启动。
从手册页...
reload-or-restart PATTERN...
Reload one or more units if they support it. If not, restart them
instead. If the units are not running yet, they will be started.
reload-or-try-restart PATTERN...
Reload one or more units if they support it. If not, restart them
instead. This does nothing if the units are not running. Note that,
for compatibility with SysV init scripts, force-reload is
equivalent to this command.
因此:(1)将 ExecReload 留空,(2)使用systemctl reload-or-restart MYSERVICE
和,(3)您应该一切就绪。
如果您确实尝试使用 ExecReload 来定义一种终止并重新启动服务的方法,它将有一个新的 PID,并且 systemd 会感到困惑。
答案2
systemd 的理念是,这reload
是可选的,并且 systemd 的用户应该知道,对于每个服务,是否应该调用reload
或者通过调用来伪装它restart
。
因此,对您的问题的回答是“它不起作用,也不应该起作用。请在下一个更高层解决这个问题。”
换句话说,systemd 希望你只实现“重新加载“如果底层服务支持真正的重新加载功能……即,重新加载不会终止并重新启动服务,也不会使服务更改其 PID。换句话说,systemd 只想反映现有的功能。
ExecReload
您可能会问自己:但是,如果我可以通过允许终止并重新启动服务来实现“假”重新加载,那不是更容易吗?然后我可以systemctl reload FOO
对所有服务使用它,而不必记住哪些服务支持它,哪些不支持?
是的,那样会更容易,但那不是 systemd 的做法。Systemd 希望调用者知道reload
服务是否存在。Systemd 希望成为现有功能的通用接口,它不想负责填补空白。
例如,puppet 假设 systemd 驱动的服务reload
没有默认终止并重新启动进程。如果 Service[] 类型添加了一种指定重新加载存在的方法,并且应该在通知时使用它,它将需要了解哪些服务具有或不具有本机重新加载。Chef 和所有其他系统也必须学习同样的事情,因为 systemd 希望在该层解决它。(MiniRant:对于启动进程,systemd 似乎是无所不知、无所挂载、无命名空间自定义的 i-do-everything-at-my-layer 系统。因此,我无法告诉您为什么它不将这种理念扩展到重新加载。也许其中一位作者可以在这里插话。)