我有一个老式的守护进程,我想使用 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 在重新加载时杀死并重新启动守护进程?
答案是,“你没有”!但我们有好消息。
systemd 的理念是重新加载是可选的,如果没有真正的重新加载功能,则应保持未定义。我将“真正的重新加载功能”定义为不会终止和重新启动服务或使服务更改其 PID 的重新加载。换句话说,systemd 只想反映存在哪些特征。
相反,您应该使用
systemctl reload-or-restart
which 如果存在则重新加载,如果不存在则重新启动。从手册页...
因此:(1) 将 ExecReload 留空,(2) 使用
systemctl reload-or-restart MYSERVICE
,(3) 你应该准备好了。如果您确实尝试使用 ExecReload 来定义杀死和重新启动服务的方法,它将有一个新的 PID 并且 systemd 会感到困惑。
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 系统。因此我不能告诉你为什么它不将这种理念扩展到重新加载。也许其中一位作者可以在这里插话。)