一、初步侦察

首先确认进程的基本信息和来源:

sudo witr -p <PID>          # 查看进程树、来源、运行时长
ps aux | grep <PID>         # 确认进程存在
cat /proc/<PID>/status      # 查看详细状态(State字段最关键)

State 字段含义:

  • R 运行中,S 可中断睡眠(正常),D 不可中断睡眠(IO等待,危险),Z 僵尸进程

二、判断进程在等什么

sudo strace -p <PID>

通过系统调用判断阻塞原因:

系统调用说明
pselect6 / select / poll + 反复 Timeout等待某个 fd 有数据,但一直没有
read 无返回阻塞读,数据来源卡住
futex等待锁或线程同步
wait4等待子进程结束
recvfrom / recv等待网络数据

本案例中 pselect6 反复超时,说明在轮询等待某些 fd,是排查的起点。


三、锁文件排查

如果怀疑是资源锁冲突:

lsof /var/lib/dpkg/lock
lsof /var/lib/apt/lists/lock
lsof /var/cache/apt/archives/lock

无输出则排除锁冲突,继续深入 fd 分析。


四、fd 深度分析(核心)

# 查看进程所有打开的文件描述符
sudo ls -la /proc/<PID>/fd/

# 判断每个fd的类型
# socket:[xxx]  → 网络连接
# pipe:[xxx]    → 管道
# /path/to/file → 普通文件

如果是 socket,检查网络状态:

sudo ss -tp | grep <PID>
# 看连接是 ESTABLISHED / CLOSE_WAIT / TIME_WAIT

如果是 pipe,找管道两端的持有者:

sudo lsof 2>/dev/null | grep <pipe_inode_id>
# 找到读端(r)和写端(w)各是哪个进程

五、死锁识别

拿到管道两端信息后,画出依赖关系图:

进程A ──写──→ pipe1 ──→ 进程B(进程B在等pipe1有数据)
进程A ←──读←── pipe2 ←── 进程B(进程A在等pipe2有数据)

判定条件:

  • A 等 B 写入才能继续
  • B 等 A 写入才能继续
  • 双方都在等,形成闭环 → 死锁确认

本案例的死锁闭环:

apt-get ──[fd8写]──→ pipe:217112098 ──→ [fd0读] http
apt-get ←──[fd5读]←── pipe:217112097 ←── [fd1写] http

六、处理死锁

死锁一旦形成无法自行恢复,必须手动介入:

# 1. 终止整条进程链(从子进程到父进程)
sudo kill -9 <child_pid1> <child_pid2> <parent_pid>

# 2. 清理残留锁文件
sudo rm -f /var/lib/apt/lists/lock
sudo rm -f /var/lib/dpkg/lock
sudo rm -f /var/cache/apt/archives/lock

# 3. 修复可能损坏的状态
sudo dpkg --configure -a

# 4. 验证恢复正常
sudo apt-get update

七、预防措施

针对本案例(apt 无限等待),配置超时:

sudo tee /etc/apt/apt.conf.d/99timeout << EOF
Acquire::http::Timeout "60";
Acquire::https::Timeout "60";
Acquire::Retries "3";
EOF

通用建议:

  • 对长时间运行的关键进程设置监控告警(运行超过阈值自动通知)
  • 定期检查 ps aux 中异常高龄进程
  • 进程间通信设计时加入超时机制,避免无限阻塞

完整排查流程总结

witr / ps 发现异常进程

cat /proc/PID/status  确认进程状态

strace -p PID  观察系统调用,判断在等什么

ls /proc/PID/fd  查看所有文件描述符类型

    ┌───────────┬───────────┐
  socket       pipe      文件锁
    ↓           ↓           ↓
  ss -tp    lsof|grep   lsof /path
  查网络     找两端       查持有者
    ↓           ↓
         画依赖图
         判断是否闭环

         kill 整条链
         清理锁文件
         修复状态
         验证恢复

这套方法论适用于所有 Linux 进程间通信死锁场景,不限于 apt,同样适用于数据库连接池、消息队列、任何使用 pipe/socket 通信的服务。

Linux进程分析与死锁排查

作者

Sawa

发布日期

2026 - 03 - 05

Avatar
Sawa

Don't Panic

分类