docker exec 对 paused 容器完全失效,因其所有进程被 cgroup freezer 内核级冻结,PID 1 无法响应 fork/exec,execve 调用直接返回 ESRCH 或 EAGAIN。
不能利用 docker exec 进入 paused 容器——该操作在技术上不可行,不是“有风险”,而是根本不会成功。
为什么 docker exec 对 paused 容器完全失效
容器处于 paused 状态时,其所有进程已被 cgroup freezer 冻结,内核层面禁止任何新任务调度、信号投递和系统调用执行。此时:
- docker exec 依赖容器内 init 进程(PID 1)派生子进程,但冻结状态下 PID 1 已被 SIGSTOP 暂停,无法响应 fork/exec 请求;
- 宿主机调用
execve到容器命名空间内会立即返回ESRCH(进程不存在)或EAGAIN(资源暂不可用),Docker daemon 捕获后直接报错Cannot exec into a paused container; - 尝试强制绕过(如修改 cgroup state 后 exec)会破坏暂停语义,等效于提前 unpause,失去“内存快照时刻”的调试前提。
误判“能 exec”带来的典型误操作风险
部分用户看到容器状态为 Up X minutes (Paused),误以为只是“暂时没干活”,仍可交互。若强行重试或依赖脚本自动 exec,将导致:
- 自动化排障流程卡死或超时失败,掩盖真实问题(如 OOM 被 freeze 前已发生);
- 反复执行
docker unpause && docker exec组合,可能在关键内存状态改变后才介入,丢失原始现场; - 误信容器“还能响应”,忽略对 freezer.state、/proc/PID/status 的实际校验,错过 cgroup 权限异常等底层故障。
真正可行的替代调试路径
针对 paused 容器,应放弃交互式入口,转向离线内存分析:
-
确认冻结状态:用
docker inspect CONTAINER | jq '.State.Status, .State.Pid'获取 PID,再检查cat /proc/PID/status | grep State应为T (stopped),且cat /sys/fs/cgroup/freezer/.../freezer.state为FROZEN; -
提取内存镜像:用
sudo gcore -o /tmp/core PID或sudo dd if=/proc/PID/mem of=/tmp/mem.bin获取完整用户态内存; -
离线符号分析:配合原容器中的二进制、so 库和 debuginfo,在宿主机用 gdb 加载 core,执行
info proc mappings、bt、x/等指令定位问题。
何时需要警惕“伪 paused”现象
极少数情况下,容器显示 paused 但实际未冻结成功(如 cgroup 权限错误、内核版本不兼容):
- 检查
/sys/fs/cgroup/freezer/.../freezer.state是否真为FROZEN,而非FREEZING(卡住)或THAWED(假状态); - 观察
ps aux | grep PID中对应进程的 STAT 列:应为T,若为R或S,说明冻结失败; - 此时容器可能仍在后台运行并消耗资源,需立即
docker kill或排查宿主机 cgroup 配置。
核心原则:paused 是内核级冻结,不是应用层休眠。调试必须基于内存快照,而非试图“唤醒它说话”。


















