容器退出码 137 排查实录:不是 OOM,是宿主机偷偷重启(SIGKILL 信号分析)
背景
一台生产服务器上的容器服务最近隔三差五退出,退出码清一色 137。团队第一反应是内存溢出(OOM),准备扩内存。
我没急着动手,先把退出码拆开看了看。
退出码 137 是什么
Linux 的退出码规范:进程退出码大于 128 时,实际含义是 128 + 信号编号。
137 = 128 + 9
9 号信号是 SIGKILL,即进程被强制杀死。
能对容器发 SIGKILL 的,主要有三类:
- 内核 OOM killer(内存不足时主动杀进程)
docker stop/systemctl stop(人为或脚本停止)- 宿主机重启(关机流程向所有进程广播)
所以"退出 137"和"内存溢出"之间,还隔着两个完全不同的可能。直接按 OOM 扩内存,方向可能是错的。
排查过程
1. 排除 OOM
查内核日志:
dmesg | grep -iE "out of memory|killed process"
干净,没有任何 OOM kill 记录。OOM 假设存疑。
2. 对齐时间线
查宿主机重启记录,和容器退出时间做交叉对比:
last reboot
uptime
journalctl --list-boots
结果:容器每次退出,时间都精确落在宿主机某次重启的时刻。
3. 定位重启来源
宿主机重启分两类:软重启(reboot/shutdown,日志里有正常关机流程)和硬重启(断电/硬件复位,日志突然中断)。查系统日志确认是硬重启后,进一步翻了硬件层的 IPMI SEL 日志定位到硬件告警触发。
根因
宿主机硬件异常触发重启,重启过程广播 SIGKILL 杀掉所有容器。和容器内存没有关系——如果当时扩了内存,问题照旧,钱白花。
经验总结
- 退出码 ≠ 根因。看到 137 先想"谁发的 SIGKILL",而不是"内存不够"。
- 时间线交叉验证是第一排查手段。容器退出时间 ↔ 宿主机重启时间 ↔ 硬件事件日志,三线一对,根因往往自己冒出来。
- 附一个退出码速查,方便以后对照:
| 退出码 | 计算 | 信号 | 优先排查方向 |
|---|---|---|---|
| 137 | 128+9 | SIGKILL | dmesg 有无 OOM;last reboot 对齐 |
| 143 | 128+15 | SIGTERM | 谁发的 stop(docker stop/脚本/systemd) |
| 139 | 128+11 | SIGSEGV | 应用自身段错误,查 coredump |
| 1~127 | — | — | 应用自己退出,看应用日志 |
关于我
Linux 运维工程师,主做服务器部署、线上排障、安全加固、自动化运维。
平时接服务器代运维和故障救火的活,这类"表面一个原因、实际另一个原因"的排障见得多。有类似问题欢迎留言或私信,先描述现象,我判断能不能帮上忙,搞不定不收费。
- 排障案例:https://github.com/wangzhi-hash/devops-portfolio
- 微信:im_wangzhi
浙公网安备 33010602011771号