细节
我们有一个systemd
包含以下相关指令的服务文件:
Type=forking
User=me
Restart=always
WantedBy
目前尚未设置该指令。
我们有一个 cron 作业来执行su –l me –c '<some command>'
.
前提条件
我们注意到:
- 服务已启动
- 用户
me
是不是登录系统
观察结果
每次 cron 作业完成执行时,System V IPC 队列就会消失,并且服务会重新启动,因为在队列上读取/睡眠的进程醒来后会发现队列已消失,因此进入失败状态。
cron 作业完成后,我们在系统日志中注意到以下内容:
… systemd[1]: Stopped User Manager for UID XXX
可能的解决方案
我们的installed
文件如下:
$ cat /etc/systemd/logind.conf.d/my-service.conf
[Login]
KillUserProcesses=no
RemoveIPC=no
问题
看完之后systemd 变更日志 230,我们仍然很困惑我们上面提到的可能的解决方案是否足够。
我们特别困惑的是additional steps are necessary to allow intentionally long-running processes to survive logout.
所报告的服务父systemd-cgls
项system.slice
使我们相信启动服务的规定步骤systemd-run
在这里不适用 - 这是真的吗?我们目前正在启动该服务systemctl start my-service.service
我们还需要lingering
为用户启用吗me
?
感谢帮助。
答案1
你甚至不需要KillUserProcesses=no
。 RemoveIPC=no
应该足够了。
为用户启用延迟me
是一种替代方案。不同之处在于它会让systemd --user
实例始终运行。
此行为由 logind.conf 中的 KillUserProcesses= 设置控制,之前的默认值“no”现在更改为“yes”。这意味着用户会话将在之后被正确清理,但需要额外的步骤才能允许故意长时间运行的进程在注销后继续存在。
引用的意思是,当且仅当 KillUserProcesses=yes 时,“额外的步骤”是允许 GNU Screen 在注销后继续运行所必需的。附加步骤基本上是systemd-run --user --scope COMMAND
, AND 启用延迟。
这与你的愿望无关。因为您的服务进程不在登录会话内运行。
您通过查看 systemd-cgls 得出的结论是完全正确的。
另一种方法是永远不要以用户身份登录me
。 su
算作一次登录。用户 crontab 可能被视为登录(除非 /etc/pam.d/cron 避免直接或间接调用 pam_systemd)。例如,您可以将 的使用替换su
为setpriv
,或者使用 systemd 计时器单元代替 cron 来启动具有User=me
.