我已经使用启动和停止守护程序的包装脚本将我的 LSB 控制的守护程序移植到 systemd。我的 systemd(多实例)服务文件使用Type=forking
、ExecStart=...
、ExecStop=...
和PIDFile=...
.
启动时,在 systemd 中一切看起来都正常,但停止似乎总是失败。由于在 LSB 环境中这工作正常,我怀疑 systemd (228) 做了一些坏事。
实际上我发现在成功启动后PIDfile 消失了,所以我的包装脚本返回退出代码 1(因为在预期的地方找不到 PID 文件)。
那么systemd真的会删除PID文件吗?副作用是,在包装脚本返回错误后,systemd 似乎很难杀死我的守护进程。
是的,当服务单元进入“死亡”状态时,systemd 会删除 pid 文件。但是,这种情况发生在服务停止后(ExecStop 完成并且进程终止)。
我建议不要为 ExecStop 使用包装脚本,因为......好吧,这就是 systemd 所做的。作为服务管理器,它知道您的守护进程的 PID(即使您不使用 pidfile)并且它可以本机发送信号来停止服务。
似乎
systemd
没有删除PID 文件;相反,由于与“好旧的 init”不兼容,我的守护进程没有创建它:在 fork()ing 之后,我的守护进程的子进程等待父进程退出,如下所示:接下来,孩子将编写 PID 文件。
如图
strace
所示,getppid()
不断返回31940
结果是 systemd 的 PID(systemd 也有另一个 PID1
)。systemd
一些魔法不相容的重育也是如此。也许问题实际上与我的服务作为“用户”服务(而不是“系统”服务)运行这一事实有关(我仍然不确定这些差异)。这个问题可能是相关的:How can I run systemd as a process with pid 1 and with pid not 1?
这个也很有用:systemd 的用户服务和系统服务有什么区别?
实际上,在我将服务从用户服务更改为系统服务后,问题确实消失了。