服务起不来时,systemctl status 只是起点:五步定位法

Linux · 3 分钟阅读· 383 次阅读

写了个 unit 文件,systemctl start 之后立刻 inactive,status 里只有一句「Failed with result 'exit-code'」。这时候最容易做的是反复重启,而不是看日志。

systemd 的错误分四类:程序自己退出、权限不足、环境变量缺失、依赖未就绪。四类的日志位置不同。

先说结论

先 journalctl -u 服务名 -n 50,再看 unit 文件的三个高危字段:ExecStart 路径、WorkingDirectory、User。

  • journalctl -u xxx -n 50 --no-pager 看真实报错
  • systemctl cat xxx 核对 unit 内容
  • 前台手动跑一遍 ExecStart 的命令
  • 检查 User/Group 与目录权限
  • 确认端口没被占、依赖服务已就绪

先把问题说清楚

systemd 不读你的 shell 环境(.bashrc 里的 PATH、代理都不生效),所以「我手动能跑」和「服务起不来」经常同时成立。

Type=simple 时 systemd 认为进程一启动就是就绪,如果程序需要几秒初始化,要配 Type=notify 或加 ExecStartPre 等待。

具体怎么做

按顺序执行,每步都验证完再进下一步:

  • journalctl -u 服务名 -n 50 --no-pager 读最近的日志
  • systemctl cat 服务名 检查 ExecStart/WorkingDirectory/User/Environment
  • 把 ExecStart 的命令复制出来,用相同用户手动执行(sudo -u www -i)
  • 检查目录属主与 SELinux/AppArmor 是否拦截
  • ss -lntp 确认端口占用;对依赖型服务用 After=/Requires= 明确顺序

参数与成本对照

把关键数值摊开,方便判断该选哪条路:

现象 常见原因 处理
status 显示 exit-code 程序自身报错退出 journalctl 看 stderr
Permission denied User 与目录属主不一致 chown 或用正确用户启动
command not found PATH 里没有该命令 ExecStart 写绝对路径
启动超时 Type 与实际不符 改 Type=notify 或加 TimeoutStartSec

服务起不来时,systemctl status 只是起点

几个容易踩的坑

下面这些是最常见的错误做法:

  • 只反复 restart:日志会滚掉,反而丢了证据
  • 在 .bashrc 里 export 变量指望 systemd 读到
  • 用 root 跑一切:出问题更难定位
  • 改完 unit 不 daemon-reload,改动不生效

最后补两句

把「手动能跑但服务不行」当成常态去排查环境差异,是最快的路径:差异只有用户、环境变量、工作目录三项。

工具是手段,理解机制才是能力。命令记不住没关系,知道「该看什么」就够了。

评论 (3)

阿
阿哲

照着做了一遍,确实少走弯路。第二步最容易漏,建议顺手加个检查清单。

南
南风

比「一键脚本」有用多了,知道为什么比知道怎么做重要。

K
Kevin

补充一句:不同版本行为会变,动手前先确认自己的版本号。

发表评论

验证码

提交后需站长审核,通过后才会显示。