iotop必须以root权限运行,因内核限制非特权用户访问/proc/pid/io;普通用户执行时所有i/o列显示为0,验证方式为sudo cat /proc/1/io可读而普通cat报permission denied。

直接看 iotop -oP,但必须用 root 权限;否则所有 I/O 列都是 0,不是 bug,是内核权限限制。
为什么普通用户运行 iotop 显示全为 0?
Linux 内核从 2.6.20 起通过 /proc/PID/io 暴露进程级 I/O 统计,但该文件默认仅对 root 或拥有 CAP_SYS_ADMIN 能力的进程可读。普通用户执行 cat /proc/1/io 会返回 Permission denied,iotop 底层正是读这个路径 —— 所以加 -u $USER 也无效,只要不是 root,DISK READ/DISK WRITE/IO% 全是 0。
验证方式:
-
sudo cat /proc/1/io可正常输出(如rchar: 123456789) -
cat /proc/1/io直接报错
iotop -oP 是定位高 IO 进程最实用的组合
-o(--only)只显示当前正在做 I/O 的进程,-P(--processes)过滤掉线程(TID),避免被 mysqld 下上百个 io_wq 线程刷屏干扰判断。
关键点:
-
IO列是「该进程等待 I/O 完成的时间占比」,不是带宽。值 >90% 表示它卡在磁盘响应上,不一定是写得多,可能是慢盘、锁竞争或 NFS 延迟 -
DISK WRITE持续 >10MB/s 且IO>80%,基本可锁定为瓶颈源 -
DISK READ高但IO低(比如 10%),说明进程读得快、不卡,可能只是批量预读或缓存命中
看到高 IO 进程后,怎么知道它在读写哪个文件?
iotop 不回答这个问题 —— 它只告诉你“谁在 IO”,不告诉你“IO 哪里”。下一步必须立刻切到:
-
lsof -p <pid></pid>:列出该进程打开的所有文件,重点关注REG(普通文件)、DIR(目录)、DEL(已删除但仍被占用的文件) -
ls -la /proc/<pid>/fd/</pid>:直接看 fd 符号链接指向哪些路径(比lsof更轻量,且不依赖外部工具) - 若需实时追踪文件级吞吐:
sysdig -p "%12s %6r %6w %s" -c fdbytes by fd.type=file | grep -v '0\s*0'
注意:lsof 在容器中可能看不到宿主机路径,此时需进宿主机查对应 PID;sysdig 需提前安装且有 CAP_SYS_ADMIN 权限。
没 root 权限时只能退而求其次
如果无法提权,iotop 直接不可用,替代方案只有设备级观测:
-
iostat -x 1:看%util和await,确认磁盘是否饱和,但无法定位到进程 -
pidstat -d 1:部分新内核支持非 root 的粗粒度 I/O 统计(仅显示 KB/s,无具体文件信息,且精度远低于iotop) - 日志分析:如 MySQL 开启
slow_query_log、Nginx 开启access_log并统计大 body 请求,间接推测 IO 源头
真正麻烦的从来不是怎么看到高 IO,而是看到之后——那个 PID 正在操作的到底是数据库 binlog、还是某个日志轮转脚本在 cat /var/log/syslog | gzip > old.gz,这一步必须靠 lsof 或 /proc/PID/fd 实锤,漏掉就容易误判。











