服务启动失败怎么查
systemd 的服务排障有一条固定路径:先用 status 拿到摘要与退出码,再用 journalctl -u 看程序自己的报错,接着弄清单元最终生效的配置,最后以服务账号手工复现一次。之所以要按顺序走,是因为 status 只给结论,日志才给原因,而配置可能被 drop-in 覆盖,不看合并结果很容易改错文件。这套流程在麒麟 V10、UOS 服务器版、openEuler 上完全通用。
基本信息
| 第一步 | systemctl status 单元 -l --no-pager 看摘要与退出码 |
|---|---|
| 第二步 | journalctl -u 单元 -n 100 --no-pager 看程序日志 |
| 第三步 | systemctl cat 单元 看合并后的最终配置 |
| 第四步 | 以服务账号手工执行 ExecStart 复现 |
| 第五步 | 修复后 reset-failed 再 start,观察是否复发 |
| 适用平台 | Kylin V10 / UOS 服务器版 / openEuler / CentOS 7+ |
四类高频根因
- 权限问题:程序、目录、证书或密钥的属主与权限不对,日志里是 Permission denied
- 端口问题:端口被占用或低端口无权限绑定,报 Address already in use 或 Permission denied
- 配置问题:路径不存在或语法错误,报 No such file or directory 或解析失败
- 资源与策略问题:句柄数、内存上限触顶,或被安全模块拒绝,需要看审计日志确认
排查命令
排查命令
systemctl status myapp --no-pager -l # 摘要与退出码
journalctl -u myapp -b --no-pager | tail -80 # 本次启动的日志尾部
systemctl cat myapp # 看合并后的最终单元配置
systemctl show myapp -p User -p ExecStart -p WorkingDirectory -p Environment # 关键字段
su -s /bin/bash appuser -c '/opt/myapp/bin/myapp -c /etc/myapp/app.conf' # 手工复现
ss -lntp | grep 8080 # 核对端口占用情况
ls -ld /opt/myapp /var/log/myapp # 核对目录属主与权限报错关键字对照
| 日志关键字 | 可能的根因 | 处理方向 |
|---|---|---|
| Permission denied | 文件或目录权限、属主不对 | 按服务账号调整属主与权限 |
| Address already in use | 端口已被其它进程占用 | 用 ss -lntp 找出占用者再决定 |
| No such file or directory | 配置或二进制路径写错 | 核对单元里的绝对路径 |
| Connection refused | 依赖的后端服务未就绪 | 先确认依赖服务与网络连通 |
| Too many open files | 句柄上限不足 | 调整服务的资源上限并重启 |
有 drop-in 片段时,直接改主单元文件可能被覆盖,必须用 systemctl cat 看合并后的最终配置,再决定改哪个文件。改完单元文件要 daemon-reload 才生效。
手工复现时环境并不完全等价:systemd 的 PATH、环境变量、工作目录、资源上限都由单元定义决定。手工跑通而服务跑不通,说明差异就在这些字段上,逐项对照 systemctl show 的输出即可。