strace能直接暴露I/O死锁卡在read、write、open或poll等系统调用上;通过-p PID配合-tt、-T、-f及-e trace精准过滤I/O调用,结合日志中长时间无返回、超时未处理、open失败等特征快速定位根因。

遇到I/O死锁时,strace能直接暴露进程卡在哪一步系统调用上,比如阻塞在read、write、open或poll等调用,无需重启服务就能定位根因。
精准附加到可疑进程并捕获实时行为
死锁发生时进程往往处于D(不可中断)或R(运行中但无响应)状态,先确认PID:
- 用
ps aux | grep your_app或pgrep -f "nginx|java|redis"查出目标PID - 立即执行:
sudo strace -p PID -tt -T -f -o /tmp/io_deadlock.log 2>&1 -
-tt带微秒级时间戳,便于比对阻塞起始点;-T显示每次调用耗时,超长耗时就是线索;-f确保子进程(如线程fork出的worker)也被追踪
聚焦I/O相关系统调用,过滤干扰噪音
默认输出包含大量无关调用(如gettimeofday、rt_sigprocmask),应主动收缩范围:
- 只看文件I/O:
sudo strace -e trace=open,read,write,close,fsync,pread,pwrite -p PID -o io_only.log - 只看网络I/O:
sudo strace -e trace=socket,connect,accept,sendto,recvfrom,select,poll,epoll_wait -p PID - 若怀疑锁文件或设备节点,加
stat和fstat:-e trace=open,read,write,stat,fstat
识别典型死锁信号特征
查看日志时重点找三类现象:
- 某次
read或recvfrom调用后长时间无返回(同一行末尾<unfinished ...></unfinished>且后续无...补全) -
poll/epoll_wait返回0或超时,但程序未做超时处理,陷入空转等待 -
open失败并返回-1 EBUSY或-1 ENOENT,而程序未检查错误就继续读写,导致后续调用挂起
结合输出快速验证与收尾分析
拿到日志后不必通读,用命令直击关键信息:
- 查所有未完成调用:
grep "<unfinished></unfinished> - 查耗时最长的5次I/O:
awk '/read|write|open/ && / = / {print $NF, $0}' /tmp/io_deadlock.log | sort -nr | head -5 - 查是否反复失败:
grep "EAGAIN\|EWOULDBLOCK\|EBUSY" /tmp/io_deadlock.log - 若发现
futex调用持续阻塞,说明是用户态锁问题,需转向pstack或gdb进一步分析
不复杂但容易忽略:死锁常发生在资源未释放(如fd未close)、文件被其他进程独占、磁盘满或NFS挂载异常等场景,strace输出里的错误码和路径名就是最直接的证据。

















