Linux 服务启动失败怎么查?用 journalctl 追踪 systemd 错误日志

在 Linux 服务器上,服务启动失败是一类很常见、也很容易被误判的问题。很多人看到网站打不开、接口无响应,第一反应是重启机器,或者反复执行 systemctl restart。但如果服务本身因为配置错误、端口冲突、权限不足或依赖服务异常而失败,重启只会让问题反复出现,甚至把原本清楚的现场日志冲掉。

Linux 服务启动失败排障与 journalctl 日志分析示意图
服务启动失败时,先用日志还原启动过程,再按错误类型逐步定位。

journalctl 是 systemd 体系下最重要的日志查看工具之一。它不只是“看日志”的命令,更适合用来还原服务从启动、加载配置、绑定端口到异常退出的完整过程。相比只看应用自己的日志文件,journalctl 能同时看到 systemd、内核、服务标准输出和错误输出里的关键信息,特别适合排查 Nginx、MySQL、Redis、Docker、PHP-FPM、自建程序等服务启动失败的问题。

先确认服务状态

排查服务启动失败时,第一步不是立刻翻大量日志,而是先用 systemctl status 服务名 看当前状态。例如排查 Nginx 可以执行:

systemctl status nginx

这条命令会告诉你服务是 activeinactivefailed,还是正在重启循环。状态页里通常还会显示最近几行日志、主进程 PID、退出码、失败时间和 systemd 给出的简短原因。如果看到 Active: failed,重点要关注 ResultExecStartMain PID 和最后几行报错。

比如 code=exited, status=1/FAILURE 说明进程主动退出,常见于配置错误、参数不合法、依赖文件不存在;如果看到 status=203/EXEC,通常表示可执行文件路径、权限或 shebang 有问题;如果服务不断自动重启,则要进一步查看更完整的日志,确认它每次退出前到底发生了什么。

用 journalctl 查看指定服务

确认服务名之后,可以用 -u 参数只查看某个 systemd unit 的日志:

journalctl -u nginx

实际排查时,日志可能很多,建议加上 -n 限制最近行数:

journalctl -u nginx -n 100

如果你刚刚执行过重启操作,可以加 --since 只看最近一段时间,避免被旧日志干扰:

journalctl -u nginx --since "10 minutes ago"

这一步的目标不是把所有日志都读完,而是找到服务启动链路中第一条真正有意义的错误。很多日志会连续报错,最后一行未必是根因。例如 Nginx 最后可能只提示 control process exited,真正原因却在前面几行,比如配置文件语法错误、证书路径不存在、端口已经被占用。

跟踪实时日志

如果服务启动失败不是每次都稳定复现,可以打开实时日志窗口,再执行重启命令观察变化:

journalctl -u nginx -f

-f 类似 tail -f,会持续输出新日志。你可以在另一个终端执行:

systemctl restart nginx

这样能看到服务启动时每一步输出。对于偶发失败、启动慢、重启循环、依赖服务尚未就绪等问题,实时日志比事后翻日志更直观。尤其是自建程序,如果日志没有单独写入文件,而是直接输出到标准输出或标准错误,journalctl -f 往往就是最直接的观察入口。

在云服务器环境里,实时日志也适合配合监控告警使用。例如网站突然不可用时,先不要盲目升级配置,可以登录服务器观察服务日志、端口监听和资源占用。如果使用的是速维云这类云服务器产品,也建议在日常运维里保留基础监控与备份策略,避免把每一次服务异常都变成临时救火。

按启动时间缩小范围

很多服务器已经运行了很久,日志里可能混着几天甚至几周的信息。为了避免误判,可以按时间筛选:

journalctl -u nginx --since "2026-06-19 10:00:00" --until "2026-06-19 10:30:00"

如果你知道故障大概发生在某个时间点,这种方式比只看最后 100 行更可靠。因为服务可能在失败后被反复重启,最后几行看到的是后续重试,而不是第一次失败的现场。

还可以用 -b 查看本次启动以来的日志:

journalctl -u nginx -b

如果问题发生在服务器重启之后,-b 很有用。它可以把上一次系统启动前的日志排除掉,让你专注于当前这次开机后服务为什么没起来。查看上一次启动周期则可以用 -b -1,适合排查“重启前发生过什么”。

常见错误怎么判断

看到日志之后,关键是把错误类型归类。第一类是配置错误。Nginx、MySQL、Redis、PHP-FPM 都很容易因为配置文件写错、路径不存在、参数不支持而启动失败。这类日志通常会出现 syntax errorunknown directivefailed to parseNo such file or directory 等关键词。处理方式是先修配置,再用服务自带的检测命令验证,例如:

nginx -t
php-fpm -t

第二类是端口冲突。日志里可能出现 address already in usebind failedcannot assign requested address。这时要查端口监听:

ss -lntp | grep ':80\|:443'

如果端口已经被其他进程占用,需要确认是不是重复启动了同类服务,或者旧进程没有正常退出。不要直接杀进程,先看进程属于哪个服务,避免误伤线上业务。

第三类是权限问题。日志中常见 permission deniedaccess deniedfailed to open。这类问题要检查文件属主、目录权限、SELinux/AppArmor、安全限制以及 systemd unit 里的运行用户。很多程序在 root 下手动运行没问题,但交给 systemd 以后失败,就是因为 systemd 使用了不同的工作目录、环境变量或运行用户。

看 unit 配置和启动命令

如果日志显示可执行文件不存在、参数错误或环境变量缺失,就要检查 systemd unit 文件。可以执行:

systemctl cat nginx

这会显示服务的 unit 配置以及覆盖配置。重点看 ExecStartUserGroupWorkingDirectoryEnvironmentRestart 等字段。自建服务尤其要注意工作目录和环境变量,因为在命令行里能运行,不代表 systemd 启动时也有同样的路径和环境。

修改 unit 文件后,不要忘记执行:

systemctl daemon-reload
systemctl restart 服务名

如果只改了配置文件但没有重新加载 systemd,服务仍可能使用旧的启动定义。排查时也可以用 systemctl show 服务名 查看 systemd 解析后的实际配置,避免被多个覆盖文件误导。

别忽略磁盘、内存和依赖服务

服务启动失败不一定都是服务本身的问题。磁盘满了、inode 用尽、内存不足、数据库没起来、网络挂载失败,都可能让应用启动失败。日志里如果出现写入失败、临时文件创建失败、连接数据库超时,就要跳出单个服务,检查系统状态:

df -h
df -i
free -h
systemctl status mysql
systemctl status redis

对于依赖数据库、缓存、消息队列的业务程序,还要看启动顺序是否合理。systemd unit 里可以通过 AfterRequires 等字段描述依赖关系,但这只能保证启动顺序,不一定保证依赖服务已经完全可用。应用本身仍应具备重试机制,否则数据库慢启动时也可能导致业务服务启动失败。

形成固定排查顺序

建议把服务启动失败的排查顺序固定下来:先看 systemctl status,确认失败状态和退出码;再用 journalctl -u 服务名 --since 定位启动时间段;然后根据日志关键词判断是配置、端口、权限、依赖还是资源问题;最后修改配置、重新加载、重启服务并回看日志确认恢复。

不要一上来就清空日志、重装服务或重启服务器。日志是故障现场,越早保留越容易定位根因。对于生产环境,还应把关键服务的配置变更、重启时间、错误日志和处理结果记录下来。下一次遇到类似问题时,你就不需要从零开始猜。

journalctl 的价值在于把“服务为什么没起来”这件事变得可追踪。掌握它之后,很多看似复杂的 Linux 服务故障,都会变成按时间线逐步确认的问题:服务什么时候启动、执行了什么命令、输出了什么错误、为什么退出、修复后是否真正恢复。只要排查顺序稳定,服务启动失败就不会再是一团乱麻。

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享