Systemd 用户服务重启后失败,但手动工作正常

Systemd 用户服务重启后失败,但手动工作正常
  • 注意:~/opt/bin/MemoryDiagnostics是一个 bash 脚本并且是可执行的。
$ cat MemoryDiagnostics.service

[Unit]
Description=MemoryDiagnostics Service

[Service]
ExecStart="%h/opt/bin/MemoryDiagnostics"
SyslogIdentifier=MemoryDiagnosticsService

[Install]
WantedBy=default.target
$ systemctl --user enable MemoryDiagnostics.service 
Created symlink /home/nikhil/.config/systemd/user/default.target.wants/MemoryDiagnostics.service → /home/nikhil/.config/systemd/user/MemoryDiagnostics.service. 

然后重新启动。观察:重启后服务失败

$ systemctl --user status MemoryDiagnostics.service 
● MemoryDiagnostics.service - MemoryDiagnostics Service
     Loaded: loaded (/home/nikhil/.config/systemd/user/MemoryDiagnostics.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Thu 2021-09-02 02:34:32 CEST; 11min ago
    Process: 1549 ExecStart=/home/nikhil/opt/bin/MemoryDiagnostics (code=exited, status=1/FAILURE)
   Main PID: 1549 (code=exited, status=1/FAILURE)

Sep 02 02:34:29 X550JX systemd[1147]: Started MemoryDiagnostics Service.
Sep 02 02:34:32 X550JX systemd[1147]: MemoryDiagnostics.service: Main process exited, code=exited, status=1/FAILURE
Sep 02 02:34:32 X550JX systemd[1147]: MemoryDiagnostics.service: Failed with result 'exit-code'.
  • 手动完成时服务启动:
$ systemctl --user start MemoryDiagnostics.service 
$ systemctl --user status MemoryDiagnostics.service 
● MemoryDiagnostics.service - MemoryDiagnostics Service
     Loaded: loaded (/home/nikhil/.config/systemd/user/MemoryDiagnostics.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2021-09-02 02:48:13 CEST; 4s ago
   Main PID: 9941 (bash)
     CGroup: /user.slice/user-1000.slice/[email protected]/MemoryDiagnostics.service
             ├─9941 bash /home/nikhil/opt/bin/MemoryDiagnostics
             └─9970 sleep 121

Sep 02 02:48:13 X550JX systemd[1147]: Started MemoryDiagnostics Service.

为什么 shell 脚本在重新启动后失败,但在手动启动时工作得很好?

答案1

~/opt/bin/MemoryDiagnostics正在退出,退出代码为 1。这意味着故障是应用程序内部的。令人失望的是,MemoryDiagnostics没有将更多信息记录到 stderr,以便我们可以帮助提供它所需的信息。但我们可以做出一些猜测:

  • 如果MemoryDiagnostics启动 GUI,则更WantedBy=default.target改为WantedBy=graphical-session.target.
  • 如果MemoryDiagnistics依赖于其他资源,我们可以添加After=到我们的[Unit]部分以确保依赖项已准备就绪。一些可能相关的依赖项可能是:
    • After=bluetooth.target如果您也在检查(或未能检查)蓝牙。
    • After=default.target如果您需要由以下机构筹集的其他服务default.target
    • 在运行此命令之前需要准备好任何其他自定义单元(可能是安装或服务)。

如果您无法确定需要准备好哪个依赖项(或者该依赖项可能需要时间才能启动,但不使用 inotify),那么您始终可以添加ExecStartPre=/bin/sleep 5人工 5 秒的启动延迟。

此方法更容易配置,但会增加不必要的延迟或有过早开始的风险。


如果您确实喜欢该ExecStartPre=sleep方法,则不一定需要立即运行它,只需经常运行即可。那么你也可以考虑使用 a*.timer来启动你的单元。在这种情况下,我会[Install]从您的服务中删除该部分,并创建以下计时器:

# ~/.config/systemd/user/MemoryDiagnostics.timer
[Unit]
Description=MemoryDiagnostics Timer

[Timer]
OnActiveSec=5s

[Install]
WantedBy=default.target

然后systemctl --user enable MemoryDiagnostics.timer让它处理执行服务。

这实际上等同于ExecStart=sleep上面的解决方案,但也为您提供了额外的能力来添加/更改以下内容:

  • OnCalendar=这将按计划运行您的诊断
  • RandomizedDelaySec=这将对服务的触发应用随机偏移,以避免同时触发大量服务。

相关内容