排查线上死锁需分层定位:先确认容器级卡死(如docker stop无响应),再判断是应用层(java线程阻塞、redis锁泄漏)还是底层运行时(containerd task死锁),按容器状态→进程行为→线程锁→运行时逐层收敛。
排查线上死锁不能只靠单一命令,关键在于分层定位:先确认是否为容器级卡死(如 docker stop 无响应),再判断是应用层死锁(如 java 线程阻塞、redis 锁未释放),还是底层运行时死锁(如 containerd task 卡住)。下面按实际排查路径组织命令组合,聚焦高效、可落地的操作。
一、快速识别容器是否处于“假死”状态
从最外层开始,确认问题表象:
-
docker ps -a | grep -E "(removing|exited)"—— 查看是否有状态异常的容器(如卡在removing或长期exited但 PID 仍存在) -
docker inspect --format='{{.State.Status}} {{.State.Pid}} {{.State.Health.Status}}' <container_id></container_id>—— 检查实际状态、宿主机 PID 和健康检查结果;若Health.Status是unhealthy但进程还在,说明应用可能已卡住 -
ps -o pid,ppid,comm,state -p $(docker inspect -f '{{.State.Pid}}' <container_id>)</container_id>—— 验证容器主进程是否真在运行,还是僵尸或不可中断状态(D状态)
二、定位应用层死锁(以 Java 容器为例)
进入容器或在宿主机上对 Java 进程做诊断:
- 先用
docker exec -it <container_id> jps -lvm</container_id>或sudo jps -lvm | grep <app_keyword></app_keyword>找到目标 Java 进程 PID - 抓线程快照:
docker exec -it <container_id> jstack -l <pid> > thread_dump.log</pid></container_id>,重点搜索java.lang.Thread.State: BLOCKED和Found one Java-level deadlock - 查 GC 压力:
docker exec -it <container_id> jstat -gc <pid> 2000 5</pid></container_id>,若FGCT(Full GC 耗时)持续上升、OU(老年代使用率)接近 100%,可能因内存不足引发线程阻塞 - 必要时导出堆快照:
docker exec -it <container_id> jmap -dump:format=b,file=/tmp/heap.hprof <pid></pid></container_id>(注意磁盘空间),后续用 VisualVM 或 JProfiler 分析大对象和引用链
三、排查分布式锁导致的逻辑死锁(如 Redis 场景)
这类“死锁”不是线程级,而是业务锁未释放造成的资源争用:
- 查容器日志中锁相关关键词:
docker logs <container_id> 2>&1 | grep -i "lock\|acquire\|release\|timeout"</container_id> - 进 Redis 检查锁 key:
redis-cli KEYS "lock:*" | head -20,再用redis-cli TTL "lock:order:12345"看剩余时间;若 TTL 为 -1,说明没设过期,极可能泄漏 - 确认锁值是否匹配持有者:
redis-cli GET "lock:order:12345",比对是否与当前服务实例标识一致(防误删) - 结合应用日志时间戳,用
docker logs --since "2026-09-25T08:30:00" --until "2026-09-25T08:45:00" <container_id></container_id>锁定故障窗口,交叉验证锁获取与释放行为
四、检查 containerd 底层 task 死锁(docker stop 卡住时必查)
当 docker stop 长时间无响应,需绕过 Docker CLI 直查 containerd:
- 查容器在 containerd 中的状态:
sudo ctr -n moby containers list | grep <container_id_prefix></container_id_prefix> - 查对应 task 是否卡住:
sudo ctr -n moby tasks ls | grep <container_id_prefix></container_id_prefix>,若 STATUS 是RUNNING或STOPPING不变,基本确认 task 层死锁 - 找并杀 shim 进程:
sudo pgrep -f "containerd-shim.*$(echo <container_id> | cut -c1-12)" | xargs sudo kill -9</container_id> - 清理残留元数据(需停 containerd):
sudo systemctl stop containerd && sudo rm -rf /var/lib/containerd/io.containerd.runtime.v2.task/moby/<container_id>* && sudo systemctl start containerd</container_id>
整个过程重在“由外向内、逐层收敛”:容器状态 → 进程行为 → 线程/锁细节 → 底层运行时。不建议一上来就 dump 堆或重启服务,优先用轻量命令快速排除常见路径。











