服务启动失败需分两步排查:先用 systemctl list-dependencies(正向/反向)和 systemctl cat 检查依赖与配置,再通过 systemctl status、journalctl 和应用日志定位首行错误,最后手动执行 execstart 命令验证环境。

服务启动失败时,真正有用的线索不在 systemctl start 那句“failed”里,而在它背后的依赖关系和运行时输出中。关键要分两步走:先看清它依赖谁、谁又依赖它,再挖出它实际崩溃时打印的那行错误。
查依赖关系:看清楚谁卡住了启动链
依赖不是单向的,得从正向和反向两个角度确认:
- 运行
systemctl list-dependencies --all 服务名.service,展开全部层级依赖(包括间接依赖),确认Requires=和Wants=列出的服务是否都处于active状态 - 执行
systemctl list-dependencies --reverse 服务名.service,找出哪些其他服务把它当依赖项——如果这些上游服务本身没启好,也会拖垮目标服务 - 用
systemctl cat 服务名.service直接查看 unit 文件,在[Unit]段核对After=、BindsTo=等字段是否拼写正确、引用的单元真实存在
挖错误日志:聚焦服务自己打出的第一行报错
systemd 只说“进程退出了”,不说为什么。真实错误藏在服务自己的输出里:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 先运行
systemctl status 服务名.service,重点关注最后几行红色日志,以及Main PID是否为空或显示已退出 - 立刻执行
journalctl -u 服务名.service -n 50 --no-pager,跳到末尾看最近 50 行,重点找:Permission denied、No such file or directory、Address already in use、segmentation fault或任意带error/fail的行 - 若刚启动过,加
--since "2 minutes ago"缩小时间范围;想实时跟踪,开一个终端跑journalctl -u 服务名.service -f,另一个终端执行systemctl start
补查应用层日志:别只信 systemd 的 journal
很多服务(如 Nginx、MySQL、Redis)不把完整错误写进 journal,而是记在自己的日志文件里:
- 查常见路径:
/var/log/nginx/error.log、/var/log/mysqld.log、/var/log/redis/redis-server.log - 用
tail -n 50 -f /path/to/log实时观察,或grep -i "error\|fail\|panic" /path/to/log快速筛选关键词 - 如果不确定日志位置,先看服务配置文件(如
/etc/nginx/nginx.conf中的error_log指令),或运行systemctl show 服务名 --property=LogsDirectory
验证配置与环境:绕过 systemd 手动试一次
有时问题出在 systemd 的封装里——比如权限、环境变量、工作目录,手动模拟能直接暴露:
- 从
systemctl cat 服务名中复制ExecStart=后的命令 - 按
User=字段切换用户,加上Environment=定义的变量,再执行该命令(例如:sudo -u www-data PATH=/usr/local/bin:/usr/bin:/bin /usr/sbin/nginx -t) - 观察终端输出:缺少动态库、配置语法错误、socket 目录不可写、端口被占等问题,这时都会原形毕露










