systemd 服务单元 Restart=on-failure 不会重新启动守护进程

systemd 服务单元 Restart=on-failure 不会重新启动守护进程

我想编写一个服务单元文件,它将启动一个守护进程并在它死掉时重新启动它。我有:

[Unit]
Description=lmgrd

[Service]
User=flexlm
Group=flexlm
ExecStartPre=/usr/bin/cp /nfs/lmgrd/* /lm/
ExecStart=/lm/lmgrd -c /lm/license.lic -l /lm/lmgrd.log
Restart=on-failure
RestartSec=3
RemainAfterExit=yes
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

这会复制文件并启动守护进程,但如果我终止守护进程 (lmgrd),它不会重新启动。我怎样才能解决这个问题?

答案1

我怀疑它没有重新启动,因为 systemd 认为该服务没有首先运行一个守护进程。如果您在守护进程仍然存在时查看systemctl status,您可能会看到“状态:活动(已退出)”并且没有列出主 PID。

默认情况下,FlexLM lmgrd 将(守护进程)启动时;初始进程几乎立即退出,而子进程是需要跟踪的“主”守护进程。

问题是 systemd 还没有被告知这一点——服务中没有 Type= 设置,默认值实际上是 Type=simple ,它告诉 systemd 跟踪最初的而是处理。因此,一旦 lmgrd 守护进程,systemd 就会认为“主”进程已退出,并且通常会报告服务已停止。

在你的情况下,systemd 仍然假装该服务仍处于“活动”状态,因为已设置 RemainAfterExit=yes,但实际上不再跟踪任何进程;仍在运行的 lmgrd 进程仅被视为剩余的子/工作进程,其退出不再影响服务状态。

为了解决这个问题,删除该RemainAfterExit=选项添加该Type=forking选项。后者是处理“守护进程”或“分叉到后台”的服务的正确方法。 (Systemd 将自动确定主进程,无需“PID 文件”。)

或者,您可以保留 Type=simple (但仍删除 RemainAfterExit!),但将流程配置为不是daemonize – FlexLM 可以-z选择“在前台运行”。

(Type=simple 通常被推荐,但并不总是更好的选择;Type=forking 还具有通知 systemd 的优点什么时候服务已经准备好了,这往往胜过Type=simple的“简单”优势。尽管这仅在守护程序正确计时其“守护程序化”时才重要 - lmgrd 不会 - 并且如果系统配置了任何服务依赖于此服务 - 在本例中也可能没有,因此-z可以使用.)

根据一般经验法则,切勿使用 RemainAfterExit=yes,除非有问题的 ExecStart预期的退出(大多数时候您还可以使用 Type=oneshot 来执行此类服务)。例如,nftables.service 可能会使用此选项,因为即使在nft进程退出后,防火墙规则集仍保持加载状态。然而,对于长期存在的守护进程,RemainAfterExit=yes 的唯一影响是负面的——它使 systemd 忽略故障。


作为补充说明,systemd才不是在 ExecStart 中展开通配符(这些命令在不使用 shell 的情况下运行,因此通常的 shell 运算符都不起作用)。该命令将尝试复制一个字面名为*.

您应该更改它以递归地复制目录的内容:

ExecStartPre=/usr/bin/cp -rv /nfs/lmgrd/. /lm/

或者运行 shell 进行通配符扩展:

ExecStartPre=/bin/sh -c "cp -v /nfs/lmgrd/* /lm/"

相关内容