用 journalctl 查服务崩溃原因:从启动失败到反复重启的排查步骤

举报
yd_226757564 发表于 2026/11/08 10:06:03 2026/11/08
【摘要】 服务起不来先别急着反复重启。本文讲用 journalctl 按状态、日志、场景分流排查:启动失败看配置、端口与权限,反复重启看重启策略与完整崩溃周期,现场丢失用 -b -1 回看上一次启动,并介绍日志清理的安全做法。

服务起不来了,第一反应往往是多执行几次 systemctl restart。但在 systemd 管理的云服务器上,反复重启只会把有用的现场日志冲掉。正确顺序是:先看状态,再看日志,最后才动手改配置。本文以常见的 nginx、sshd 这类服务为例,讲一套用 journalctl 排查服务崩溃的通用步骤。

一、先看状态,确认服务到底卡在哪一步

systemctl status nginx --no-pager
systemctl is-enabled nginx

systemctl status 会同时给出三类关键信息:服务当前是 active、failed 还是 activating;最近一次启动的退出码;以及最后十几行日志。常见的 Result: exit-code 说明进程自己退出了,Result: timeout 说明启动超时,Result: start-limit-hit 则说明短时间内启动太频繁,被 systemd 限流了。先把这个结果记下来,它决定了下一步该看哪一段日志。

二、用 journalctl 看本服务的完整日志

只看 status 的尾部日志常常不够,因为它只截取了最后一段。按服务名过滤,才能看到从启动到退出的完整过程:

journalctl -u nginx --no-pager -n 100
journalctl -u nginx --no-pager --since "2026-11-08 09:00:00"
journalctl -u nginx -f

-n 100 看最近 100 行,--since 按时间缩小范围,-f 实时跟随,适合在另一个终端执行 restart 时同步观察。只想看错误时可以加级别过滤:

journalctl -u nginx -p err --no-pager -n 50

-p err 只显示错误及以上级别,能快速跳过大量正常启动信息。如果服务名不确定,先用 systemctl list-units --failed 列出当前所有失败的单元,再逐个排查。

三、场景一:服务启动就失败

这是最常见的情况。按下面顺序对照日志找原因:

  1. 配置文件写错了。 日志里出现 emerg、unknown directive、invalid number of arguments 这类字样,一般是配置文件语法错误。先用服务自带的检查命令验证,例如 nginx -t、sshd -t,改完再启动。
  2. 端口被占了。 日志提示 bind() to 0.0.0.0:80 failed (98: Address already in use),说明端口已被别的进程占用。用 ss -tlnp | grep ':80' 找到占用进程,确认是重复启动了同一个服务,还是两个服务抢了同一个端口。
  3. 权限或路径不对。 日志出现 Permission denied、No such file or directory 时,检查配置文件里引用的证书、数据目录、PID 文件路径是否存在,以及运行用户的读写权限。不要图省事直接把目录改成 777,先确认应该由哪个用户、哪个组来读写。
  4. 依赖没起来。 有的服务依赖网络或挂载点,日志里会出现 Network is unreachable 或找不到挂载路径。此时检查 After=、Requires= 依赖关系,以及服务启动时依赖的资源是否就绪。

改完配置后不要只重启一次就下结论,用 systemctl status 确认状态是 active,再用 journalctl -u 服务名 -n 20 确认没有新的报错。

四、场景二:服务反复重启,停不下来

如果日志里同一段启动信息每隔几秒就重复出现,说明服务在不断崩溃、不断被拉起。先看重启策略:

systemctl cat nginx | grep -E "Restart|StartLimit|ExecStart"

Restart=on-failure 会让失败的服务自动重启,StartLimitIntervalSec 和 StartLimitBurst 则限制短时间内的重启次数。一旦触发上限,服务会进入 failed 状态并停止尝试,这时 status 里会出现 start-limit-hit。

排查这类问题不要盯着最后一次启动看,要把一个完整崩溃周期内的日志连起来读:从哪一行开始启动、哪一行报错、退出码是多少、隔多久又重新启动。退出码也值得记录:退出码 1 通常是程序自身的配置或运行时错误,退出码 134(SIGABRT)、137(SIGKILL,常与内存不足有关)则要结合系统日志一起看。

journalctl -u nginx --no-pager --since "10 minutes ago" | grep -E "error|failed|exit|killed" -i

如果日志里反复出现内存不足、连接数耗尽、磁盘写满的提示,修重启策略只是掩盖问题,要先解决资源瓶颈。

五、场景三:上次启动时崩溃,重启后现场没了

服务崩溃后有人重启了服务器,或者服务自己重启后恢复了,这时当前日志里已经看不到崩溃瞬间。journalctl 可以按启动次序回看:

journalctl --list-boots
journalctl -b -1 -p err --no-pager -n 100
journalctl -u nginx -b -1 --no-pager -n 100

--list-boots 列出历次启动记录,-b -1 表示上一次启动。结合内核日志一起看,往往能发现关键线索,例如 Out of memory: Killed process 说明进程是被系统因内存不足杀掉的,这时要检查内存占用趋势,而不是只重启服务。

需要注意一点:如果 journal 日志只保存在内存里(没有持久化目录),重启后旧日志就找不到了。可以在 /var/log/journal/ 目录存在的前提下确认日志是否持久化;没有该目录时,重启前的日志默认不会保留,重要服务器建议提前配置好持久化。

六、日志太多、磁盘太满怎么办

journal 日志默认会占用一定磁盘空间,长期不清理可能把系统盘写满。先看占用:

journalctl --disk-usage
journalctl --vacuum-size=500M
journalctl --vacuum-time=14d

--vacuum-size=500M 把日志总量压缩到 500M 以内,--vacuum-time=14d 只保留最近 14 天。不要直接删除 /var/log/journal/ 下的文件,正在写入的日志文件被删后可能导致后续日志无法正常记录,用 journalctl 自带的清理命令更安全。

七、一份可直接照做的排查清单

  1. systemctl status 服务名 --no-pager:确认状态与退出码。
  2. journalctl -u 服务名 -n 100 --no-pager:看完整启动过程。
  3. journalctl -u 服务名 -p err:只看错误,定位报错行。
  4. 按报错类型分流:配置文件用自带检查命令验证,端口占用用 ss 找进程,权限问题核对路径与运行用户。
  5. 反复重启时看 Restart 与 StartLimit 配置,并把一个完整崩溃周期连起来读。
  6. 崩溃现场已丢失时用 journalctl -b -1 回看上一次启动。
  7. 改完配置先验证、再启动、再确认日志里没有新的报错。

总结

journalctl 的价值不在于命令多,而在于它把服务日志、系统日志和启动记录放在同一个时间线上。遇到服务崩溃时,先看状态定方向,再用 -u、--since、-p、-b 把日志范围收窄,最后按启动失败、反复重启、历史崩溃三种场景分流处理。把这套步骤固定下来,大多数服务起不来的问题,都能在重启之前找到真正的原因。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。