首页/系统/Linux 运维命令速查/场景:服务反复崩溃怎么查日志

场景:服务反复崩溃怎么查日志

服务 restart 循环:从 systemd 状态到应用日志逐层定位,先看退出码,再看崩溃前最后输出与内核记录。

Linux 运维命令速查系统更新于 2026-10-13

场景概述

服务反复崩溃时,日志分散在三处,排查顺序也应当固定:systemd 侧给出退出码与是否触发启动频率限制,应用侧给出崩溃前的最后输出,内核侧负责解释「进程为什么突然不见了」(OOM 击杀或段错误)。先看退出码能大幅缩小范围——退出码是应用自己返回的,说明它遇到了业务或配置问题;被信号杀掉(如 137 对应 SIGKILL),则多半是资源或运维动作。

场景信息

触发条件systemd 服务反复重启,或启动后短时间内再次退出
排查目标确定崩溃原因属于应用逻辑、资源限制还是外部杀进程
工具链systemctl status 与 show 看退出码 → journalctl -u 看应用输出 → dmesg 与 journalctl -k 看内核处置
退出码速查1 常见于通用错误;126 命令不可执行;127 找不到命令;137 与 143 分别对应被 SIGKILL 与 SIGTERM 终止;203 表示 systemd 无法执行命令

常见崩溃类型

  • 配置或依赖问题:启动时连不上数据库、证书读不到,进程自行退出并返回非 0
  • 内存不足:被内核 OOM 击杀,退出码表现为被信号终止,dmesg 有明确记录
  • 代码缺陷:空指针、断言失败或未捕获异常导致进程段错误或异常退出
  • 启动频率限制:短时间内反复重启触发 StartLimitBurst,systemd 拒绝再拉起
  • 依赖服务未就绪:未声明 After 与 Requires,启动顺序不稳定导致间歇性失败
  • 文件描述符或线程数限制:LimitNOFILE 等设置过低,运行一段时间后崩溃

四步定位命令

四步定位命令
# 第 1 步:退出码与重启次数
systemctl status myapp --no-pager -l
systemctl show myapp -p ExecMainStatus,ExecMainCode,NRestarts,Result
# 第 2 步:应用崩溃前的最后输出
journalctl -u myapp -n 200 --no-pager
journalctl -u myapp --since '10 min ago' | grep -iE 'error|exception|fail|panic|assert'
# 第 3 步:判断是否被内核处置
dmesg -T | grep -iE 'oom|killed process|segfault' | tail
journalctl -k --since '10 min ago' | grep -i oom
# 第 4 步:核对单元定义与运行环境
systemctl cat myapp
sudo -u appuser /opt/myapp/bin/start --config /etc/myapp/app.conf; echo "exit=$?"
ulimit -n; systemctl show myapp -p LimitNOFILE

退出码与方向

退出码来源排查方向
1应用自身返回配置错误、依赖不可用等业务层问题
126 / 127shell 语义可执行权限不足或解释器、命令不存在
137被 SIGKILL 终止常见于 OOM 击杀或人工强制停止
143被 SIGTERM 终止正常停止流程或编排系统下发终止
203systemd 保留段ExecStart 路径、权限或可执行格式有问题
Result=start-limit-hitsystemd 状态触发启动频率限制,需 reset-failed 后排查根因
判断「谁杀了进程」有明确的分工:退出码 137 与 dmesg 里对应的 killed process 记录同时出现,才能确认是 OOM 击杀;只有 137 而没有内核记录时,更可能是人工操作或编排系统下发的强制停止。两者的处置方向完全不同——前者要调内存与限额,后者要查是谁、为什么下发了停止动作,混为一谈会让排查长期停在错误方向上。
频繁重启与启动频率限制:systemd 默认在 10 秒内重启超过 5 次会进入 start-limit-hit 状态并停止尝试,此时 systemctl start 也会失败。先 systemctl reset-failed 清除状态,再排查根因;把 Restart 改为 on-failure 并合理设置 RestartSec,可以避免无效重启掩盖真实报错。
排查阶段先把自动重启停掉(systemctl stop),否则单元会不断重启并滚动刷掉日志缓冲,既看不清崩溃前的输出,也可能因为反复占用资源引发更大范围的影响。确认根因后再恢复并观察一段时间。

先分清失败阶段

阶段特征证据来源
启动前单元与路径校验失败单元状态与执行错误码
启动中进程立即退出退出码与标准错误
运行中运行一段时间后崩溃崩溃前日志与转储
被外部终止收到信号而结束内核与资源限制记录
拒绝再拉起触发启动频率限制单元状态提示
排查前先把自动重启关掉或延长重启间隔,否则日志被反复滚动覆盖,崩溃前的关键输出很难还原;同时记录每次崩溃的时刻,与内存、磁盘、下游依赖的波动对齐,往往能直接看出是资源周期还是业务高峰触发。

易错点

  • 只盯应用日志不看 systemd 状态,会漏掉启动前错误:WorkingDirectory 不存在、User 不对、ExecStart 权限不足都会在 exec 阶段就失败
  • 看到 137 就断定是内存不足:还需 dmesg 里的 OOM 记录佐证,否则可能是编排系统或人工下发的强制终止
  • 触发 StartLimitBurst 后 systemd 拒绝再拉起,误以为服务彻底坏了;用 systemctl reset-failed 清除状态后继续排查
  • 不关闭自动重启就开始排查,日志被不断滚动覆盖,崩溃前的关键输出难以还原
  • 忽略 ulimit 与 LimitNOFILE 之类的资源上限:应用运行一段时间后崩溃,往往与服务启动时继承的限制有关
  • 在自动重启开启的状态下反复复现:日志被不断截断,崩溃现场一次次被覆盖,正确顺序是先稳住触发条件再收集证据

数据来源与参考

  • man 5 systemd.service(退出码)
  • man 1 systemctl
  • systemd 官方文档 Troubleshooting

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌