mediation.service
我有一个这样的服务单元文件:
[Unit]
Description=Mobile-IP Log dumper
[Service]
Type=forking
ExecStart=/opt/mediation/mediation start
ExecStopPost=/opt/mediation/mediation stop
ExecReload=/opt/mediation/mediation reload
PIDFile=/var/lib/mediation/syslog-ng.pid
现在假设有人直接使用/opt/mediation/mediation start
而不是使用systemctl start mediation
在这种情况下systemctl status mediation
将显示:
● mediation.service - Mobile-IP Log dumper
Loaded: loaded (/etc/systemd/system/mediation.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2016-07-11 11:24:11 CEST; 8s ago
Process: 14088 ExecStopPost=/opt/mediation/mediation stop (code=exited, status=0/SUCCESS)
Process: 13482 ExecStart=/opt/mediation/mediation start (code=exited, status=0/SUCCESS)
Main PID: 13746
是否有可能systemctl status mediation
显示服务的正确状态(即正在运行)?看起来 systemctl 在检查状态时不会重新加载 PIDFile,因为在这种情况下所有信息都是可用的,并且正确的状态是已知的。
答案1
不,你不能这么做。
systemd 的服务跟踪主要基于 cgroups,因此进程不能除非它位于适当的 cgroup 内,否则将被视为其中的一部分mediation.service
。(例如,用户登录与 sshd.service 分离的方式是:通过移动到另一个 cgroup。)它不太关心 PID 文件,尽管它确实使用它们进行额外的验证。
但即使手动将进程移至正确的 cgroup(通过 /sys/fs/cgroup/systemd),整个服务仍不会被视为“活跃”,除非它已启动通过systemd。
在 Debian 和其他仍然混合/etc/init.d
使用脚本的发行版中,可以通过编辑常见的“LSB 函数”脚本来解决此问题,以便在手动调用时通过 systemctl 自动重新运行 initscript。
但至于启动守护进程直接地… 好吧,我想最好不要这么做?或者,制作一个类似的包装脚本,将手动启动重定向到 systemctl。
答案2
由于没有直接的解决方案,解决方法可能是将这样的行添加到脚本中。
if [[ ! `ps --no-headers -o args -p $PPID | grep systemd` ]] ; then
echo "You must start the application with 'systemctl start mediation'"
exit 1
fi
这可以防止服务在 systemctl 之外启动。