在 Linux 中排查哪些进程正在读写硬盘时,必须使用 sudo iotop -o -P,否则看到的结果几乎全是 0。原因在于内核有明确限制,普通用户无权读取 /proc/PID/io。而 sudo iotop -o -P 可以过滤掉静默进程和线程干扰,更精准地聚焦真实的磁盘 I/O 行为,再结合 lsof -p 进一步定位具体读写的文件。

排查 Linux 哪些进程在读写硬盘时,必须用 sudo iotop -o -P,否则显示结果通常全是 0 —— 普通用户无法读取 /proc/PID/io,这是内核层面的硬限制,并不是权限配置错误。
为什么普通用户运行 iotop 显示全为 0
从 Linux 内核 2.6.20 开始,进程级 I/O 统计信息文件 /proc/PID/io 就被限制为仅 root 用户可读。普通用户如果直接执行 cat /proc/1/io,通常只会看到 Permission denied;而 iotop 正是依赖这个文件来获取磁盘 I/O 数据,读取失败后,自然只能把结果显示为 0。
因此,即使加上 -u $USER,或者用 sudo -u nobody iotop 这类方式切换用户,只要运行进程本身没有 CAP_SYS_ADMIN 能力,所有 DISK READ/DISK WRITE 列依然会持续显示为 0。
验证方法也很简单:执行 sudo cat /proc/1/io | grep read_bytes 可以看到实际数值;去掉 sudo 后再试,命令就会直接失败。
sudo iotop -o -P 是排查磁盘 I/O 的可靠起点
这个命令组合能够过滤静默进程与线程噪音,只显示当前真正正在块设备上执行读写的用户态进程:
• -o(--only):仅显示有 I/O 活动的进程,像 sshd、systemd 这类当前没有发起磁盘读写的进程会被跳过,避免输出过于杂乱
• -P(--processes):按进程维度合并同一 PID 下的所有线程,否则一个 Java 进程下几十个 TID 全部展开,实际排查时非常难看清楚
• 进入界面后按 Shift+P 可以按 IO> 排序 —— 数值较高(例如 >90%)通常表示进程大量时间在等待磁盘响应,这往往比单看带宽更早暴露性能瓶颈
• 如果 DISK WRITE 持续 >10MB/s 且 IO> >80%,通常可以基本锁定它就是主要写入来源;但如果 IO> 很高而带宽很低(如 200KB/s),更可能是小文件高频刷盘、元数据操作频繁,或存在锁竞争,而不一定是吞吐量瓶颈
发现高 IO 进程后,下一步一定要查它在写哪个文件
iotop 只能回答“是谁在做 I/O”,却不能直接告诉你“它在读写什么文件”。这时应立即继续执行:
• sudo lsof -p :列出目标进程打开的所有文件描述符,重点关注 REG 类型并且带 w 写权限的记录
• sudo ls -l /proc/:直接查看 fd 符号链接最终指向的路径,相比 lsof 更底层,有时也更直观、更少误判
• 如果 NAME 列末尾出现 (deleted),说明文件已经被 rm 删除,但文件描述符还未关闭,此时磁盘空间仍不会真正释放
• 在容器环境下要特别注意:这里的 PID 是宿主机视角,lsof 必须在宿主机上执行;同时如果容器使用了独立 PID namespace,而不是 --pid=host,排查时更要结合宿主机进程视图来判断
替代方案:没有 root 权限时只能退回设备级观察
如果确实拿不到 root 权限,那么 iotop 基本就无法正常发挥作用。这种情况下还能临时用于排查磁盘性能问题的,主要有以下几种:
• iostat -x 1:重点观察 %util 和 await,先判断瓶颈是否出在磁盘设备层,但它无法继续定位到具体是哪个进程在读写硬盘
• pidstat -d 1:前提是你已经知道目标 PID,而且在非 root 环境下,输出中的 kB_wr/s 可能并不完全准确,因为它同样依赖 /proc/PID/io
• atop -d:部分 Linux 发行版会预装,按 d 键可以切换到磁盘视图,不过同样需要 root 权限,才能完整显示进程信息和进程名
• 至于 top 或 htop,不要抱太大期待:它们本身并不负责统计磁盘 I/O,iotop 里的 IO> 列在 top 中根本不存在
真正棘手的往往不是“如何查看高 IO 进程”,而是看到进程之后,发现它写入的是一个日志轮转中的临时文件,或者正在被 rsync --delete 扫描整个 /var 目录——这些关键上下文,iotop 一条命令本身并不会告诉你,还需要结合 cat /proc/、进程启动参数以及具体业务逻辑交叉分析,才能准确判断问题根因。
