bigywater.tech
Docker · 33

容器退出码:137、143、139 分别意味着什么

容器退出码 137、143、139 分别是什么意思?这篇逐个把它们复现出来,并说明哪些是程序自己返回的、哪些是被信号杀死的、哪些是 docker 本身报的错,以及如何区分同样是 137 的 OOM 和手动 kill。

128 + N
被信号 N 杀死的进程的退出码,如 TERM 15 → 143、KILL 9 → 137、SEGV 11 → 139
137 vs OOMKilled
同样的 137,OOM 杀死时 OOMKilled=True,docker kill 时为 False
125 / 126 / 127
docker 自己出错 / 命令不可执行 / 命令不存在

程序自己的退出码

实测 · 本机执行输出
  exit 0:docker run 退出码 0;Status=exited State.ExitCode=0 OOMKilled=False
  exit 3:docker run 退出码 3;Status=exited State.ExitCode=3 OOMKilled=False
  命令不存在:docker run 退出码 127;Status=created State.ExitCode=127 OOMKilled=False
  文件存在但不可执行(/etc/hostname):docker run 退出码 126;Status=created State.ExitCode=126 OOMKilled=False
  sh -c 里调用不存在的命令:docker run 退出码 127;Status=exited State.ExitCode=127 OOMKilled=False

exit N 就是 N。命令找不到是 127,找到但不能执行是 126——这两种情况容器根本没有真正启动,Status 是 created。在 sh -c 里调用不存在的命令,也是 127,但容器已经启动并 exited。

125

实测 · 本机执行输出
  不存在的选项 --foo:docker run 退出码 125;(没有创建出容器)

docker run 自己的错误(例如不存在的选项)是 125,不会创建容器。

信号

实测 · 本机执行输出
  python 自己 SIGSEGV:docker run 退出码 139;Status=exited State.ExitCode=139 OOMKilled=False
  python os.abort()(SIGABRT):docker run 退出码 139;Status=exited State.ExitCode=139 OOMKilled=False
  PID 1 的 sh 里依次起子 sh 并让它向自己发信号,子进程的退出状态($?):TERM -> 143;INT -> 130;ABRT -> 134;SEGV -> 139;KILL -> 137;Terminated;Aborted;Segmentation fault;Killed
  docker kill(默认 SIGKILL):Status=exited State.ExitCode=137 OOMKilled=False
  docker kill -s TERM,PID 1 是 sleep(没装处理程序):Status=running State.ExitCode=0 OOMKilled=False
  docker stop -t 2,PID 1 是 sleep:Status=exited State.ExitCode=137 OOMKilled=False
  --init 下 docker stop,子进程 sleep 被 SIGTERM 杀死:Status=exited State.ExitCode=143 OOMKilled=False
  --init 下 docker kill -s INT:Status=exited State.ExitCode=130 OOMKilled=False

被信号杀死的进程的退出码是 128 加信号编号。PID 1 是特殊的:没有安装信号处理程序时,内核不会让它被 TERM 杀死,docker stop 要等满超时后用 KILL,于是得到 137;加 --init 后由 init 转发,子进程被 TERM 杀死,得到 143。python 的 os.abort() 我预期是 134,实际得到 139,原因我没有查。

OOM

实测 · 本机执行输出
  内存限制 20m,python 一直申请内存:docker run 退出码 137;Status=exited State.ExitCode=137 OOMKilled=True

137 既可能是 OOM,也可能是 kill。看 docker inspect 的 State.OOMKilled:内存限制下被杀是 True,docker kill 是 False。

分步演示

容器退出码
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。每种情形运行一次(退出码是确定性的);信号用 docker kill、sh 内的 kill 和 python 触发;--init 使用 Docker 内置的 init;实验后已删除容器
    • 没有验证:Windows 容器的退出码、被内核之外的 OOM(如 cgroup v1)杀死的表现、退出码超过 255、docker wait 与 docker events 里的 exitCode、os.abort() 为什么是 139
    京ICP备2026067502号-1京公网安备11010502063487号