iotop命令是一个用于监控磁盘I/O使用情况的工具,它以类似top命令的交互式界面显示系统中各进程的磁盘读写活动。它可以帮助系统管理员识别导致高I/O负载的进程,是诊断系统性能问题的重要工具。
iotop不是所有Linux发行版的默认安装组件,可能需要手动安装:
# Ubuntu/Debian
sudo apt-get install iotop
# RHEL/CentOS 7
sudo yum install iotop
# RHEL/CentOS 8/Fedora
sudo dnf install iotop
# Arch Linux
sudo pacman -S iotop
# 验证安装
iotop --version
iotop [选项]
| 选项 | 说明 |
|---|---|
-o, --only |
只显示正在产生I/O的进程 |
-b, --batch |
非交互模式,适合脚本中使用 |
-n NUM, --iter=NUM |
设置迭代次数(配合-b使用) |
-d SEC, --delay=SEC |
设置刷新间隔(默认1秒) |
-p PID, --pid=PID |
只监控指定的PID |
-u USER, --user=USER |
只监控指定用户的进程 |
-P, --processes |
只显示进程,不显示线程 |
-a, --accumulated |
显示累计I/O |
-k, --kilobytes |
使用KB为单位(默认) |
-t, --time |
添加时间戳 |
-q, --quiet |
不显示头部信息(第一、三行) |
-h, --help |
显示帮助信息 |
-V, --version |
显示版本信息 |
iotop运行时的交互式界面包含多个部分:
Total DISK READ: 0.00 B/s | Total DISK WRITE: 0.00 B/s
Current DISK READ: 0.00 B/s | Current DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % systemd
2 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % kthreadd
3 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % ksoftirqd/0
| 字段 | 说明 |
|---|---|
| TID | 线程ID(进程ID) |
| PRIO | I/O优先级(be/best effort,rt/real time,id/idle) |
| USER | 进程所有者 |
| DISK READ | 磁盘读取速度 |
| DISK WRITE | 磁盘写入速度 |
| SWAPIN | 进程交换空间的百分比 |
| IO | 进程I/O等待时间的百分比 |
| COMMAND | 进程名称/命令 |
# 以root用户运行iotop
sudo iotop
# 或者使用
iotop -o
# 输出示例:
# Total DISK READ: 15.34 M/s | Total DISK WRITE: 8.21 M/s
# Current DISK READ: 15.34 M/s | Current DISK WRITE: 8.21 M/s
# TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
# 1234 be/4 mysql 12.45 M/s 2.34 M/s 0.00 % 45.23 % mysqld
# 5678 be/4 backup 2.89 M/s 5.87 M/s 0.00 % 12.34 % rsync
# 只显示正在执行I/O操作的进程
sudo iotop -o
# 每隔2秒刷新一次
sudo iotop -o -d 2
# 输出示例:
# Total DISK READ: 15.34 M/s | Total DISK WRITE: 8.21 M/s
# TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
# 1234 be/4 mysql 12.45 M/s 2.34 M/s 0.00 % 45.23 % mysqld
# 批处理模式,运行3次后退出
sudo iotop -b -n 3
# 批处理模式,每2秒采样一次,共采样5次
sudo iotop -b -d 2 -n 5
# 批处理模式并输出到文件
sudo iotop -b -n 5 > iotop_output.txt
# 带时间戳的批处理输出
sudo iotop -b -t -n 3
# 监控特定PID的进程
sudo iotop -p 1234
# 监控多个PID
sudo iotop -p 1234,5678,9012
# 监控特定用户的所有进程
sudo iotop -u mysql
# 监控多个用户
sudo iotop -u mysql,postgres
# 显示累计的I/O统计(从启动开始)
sudo iotop -a
# 只显示活跃进程的累计I/O
sudo iotop -ao
# 输出示例:
# Total DISK READ: 1.45 G | Total DISK WRITE: 890.12 M
# TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
# 1234 be/4 mysql 1.20 G 450.67 M 0.00 % 45.23 % mysqld
# 使用KB为单位(默认)
sudo iotop -k
# 以人类可读格式显示(自动选择单位)
# 注:iotop默认已使用人类可读格式
# 查看原始字节数(在一些版本中可能需要其他工具配合)
在iotop交互式界面中可以使用以下快捷键:
左右箭头:改变排序字段(按读写速度排序)
r:反转排序顺序
o:只显示活跃I/O进程(切换开关)
p:只显示进程(不显示线程)
a:显示累计I/O(切换开关)
i:改变优先级过滤(只显示特定优先级的进程)
q:退出
任何其他键:强制刷新显示
#!/bin/bash
# 监控高I/O进程的脚本
THRESHOLD_READ=10M # 读取阈值
THRESHOLD_WRITE=5M # 写入阈值
echo "检查高I/O进程..."
sudo iotop -b -n 3 | awk -v read_th="$THRESHOLD_READ" -v write_th="$THRESHOLD_WRITE" '
BEGIN {
# 转换阈值
read_th_num = read_th
write_th_num = write_th
if (read_th ~ /[Kk]$/) {
read_th_num = read_th_num * 1024
} else if (read_th ~ /[Mm]$/) {
read_th_num = read_th_num * 1024 * 1024
} else if (read_th ~ /[Gg]$/) {
read_th_num = read_th_num * 1024 * 1024 * 1024
}
# 类似处理write_th_num...
}
/TID/ && /PRIO/ { # 跳过表头
next
}
{
# 解析行并检查阈值
# 注意:实际解析需要根据iotop输出格式调整
print "分析中..."
}'
sudo iotop -o -d 5
# 监控30秒,每秒采样
sudo iotop -b -d 1 -n 30 > iotop_monitor.log
iostat、vmstat、pidstat一起分析原因:通常是因为权限不足或内核配置问题。
解决方案:
# 1. 使用root权限运行
sudo iotop
# 2. 检查内核配置
cat /boot/config-$(uname -r) | grep CONFIG_TASKSTATS
cat /boot/config-$(uname -r) | grep CONFIG_TASK_DELAY_ACCT
cat /boot/config-$(uname -r) | grep CONFIG_VM_EVENT_COUNTERS
# 3. 加载必要的内核模块
sudo modprobe taskstats
sudo modprobe task_delayacct
# 4. 检查/proc文件系统
ls -la /proc/$$/task/*/io
# 5. 更新内核(如果上述模块不存在)
原因:可能的原因包括:
解决方案:
# 1. 启用内核I/O记账
echo 1 | sudo tee /proc/sys/kernel/task_delayacct
# 2. 永久启用(添加到/etc/sysctl.conf)
echo "kernel.task_delayacct = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# 3. 检查是否真的没有I/O活动
# 运行一个磁盘密集型命令测试
dd if=/dev/zero of=/tmp/testfile bs=1M count=100 oflag=direct
# 4. 使用其他工具验证
sudo iostat -x 1 3
解决方案:使用批处理模式配合日志记录
# 1. 简单监控日志
sudo iotop -b -d 2 -n 60 > /var/log/iotop_monitor.log
# 2. 带时间戳的详细监控
sudo iotop -b -t -d 5 -n 24 > /var/log/iotop_$(date +%Y%m%d).log
# 3. 使用tee同时查看和记录
sudo iotop -b -d 1 -n 30 | tee /tmp/iotop_realtime.log
# 4. 定期监控脚本
#!/bin/bash
LOG_DIR="/var/log/iotop"
mkdir -p $LOG_DIR
LOG_FILE="$LOG_DIR/iotop_$(date +%Y%m%d_%H%M%S).log"
echo "开始I/O监控,持续5分钟..." | tee $LOG_FILE
sudo iotop -b -d 2 -n 150 >> $LOG_FILE
echo "监控完成" | tee -a $LOG_FILE
iostat系统级I/O统计,显示磁盘利用率
iostat -x 1 3
vmstat虚拟内存统计,包括I/O信息
vmstat 1 5
pidstat进程级统计,包括I/O
pidstat -d 1
lsof查看进程打开的文件,包括磁盘文件
lsof -p 1234
dstat多功能系统资源统计工具
dstat -d
atop高级系统监控,包括I/O
atop
#!/bin/bash
# I/O性能问题诊断脚本
LOG_FILE="/tmp/io_diagnose_$(date +%Y%m%d_%H%M%S).log"
echo "=== I/O性能诊断报告 $(date) ===" > $LOG_FILE
echo "" >> $LOG_FILE
# 1. 系统基本信息
echo "1. 系统信息:" >> $LOG_FILE
echo "主机名: $(hostname)" >> $LOG_FILE
echo "内核版本: $(uname -r)" >> $LOG_FILE
echo "系统运行时间: $(uptime)" >> $LOG_FILE
echo "" >> $LOG_FILE
# 2. 磁盘空间信息
echo "2. 磁盘空间使用情况:" >> $LOG_FILE
df -h >> $LOG_FILE
echo "" >> $LOG_FILE
# 3. 当前高I/O进程(iotop)
echo "3. 当前高I/O进程(iotop):" >> $LOG_FILE
echo "运行iotop 5秒..." >> $LOG_FILE
timeout 5 sudo iotop -b -n 5 >> $LOG_FILE 2>&1 || echo "iotop执行失败或超时" >> $LOG_FILE
echo "" >> $LOG_FILE
# 4. iostat信息
echo "4. 磁盘I/O统计(iostat):" >> $LOG_FILE
iostat -x 1 3 >> $LOG_FILE 2>&1 || echo "iostat未安装" >> $LOG_FILE
echo "" >> $LOG_FILE
# 5. 内存和交换信息
echo "5. 内存和交换使用情况:" >> $LOG_FILE
free -h >> $LOG_FILE
echo "" >> $LOG_FILE
# 6. vmstat信息
echo "6. 系统性能统计(vmstat):" >> $LOG_FILE
vmstat 1 3 >> $LOG_FILE 2>&1
echo "" >> $LOG_FILE
echo "诊断报告已生成: $LOG_FILE"
echo "请检查报告中的高I/O进程和磁盘使用情况"
#!/bin/bash
# I/O监控告警脚本
THRESHOLD_READ=50M # 读取速度告警阈值
THRESHOLD_WRITE=30M # 写入速度告警阈值
THRESHOLD_IO=80 # I/O等待时间百分比阈值
ALERT_EMAIL="admin@example.com"
LOG_FILE="/var/log/io_alert.log"
# 获取当前高I/O进程信息
echo "$(date): 开始I/O监控检查..." >> $LOG_FILE
# 使用iotop批处理模式获取数据
sudo iotop -b -n 3 -P -k > /tmp/iotop_tmp.log 2>/dev/null
if [ $? -ne 0 ]; then
echo "$(date): 错误:无法执行iotop" >> $LOG_FILE
exit 1
fi
# 分析数据(简化版,实际需要根据iotop输出格式解析)
HIGH_IO_PROCESSES=0
# 检查是否有进程超过阈值
# 注意:这里使用简化逻辑,实际应解析iotop输出
while read -r line; do
# 这里应该解析每行数据,提取READ, WRITE, IO%等值
# 简化示例:假设我们检测到高I/O
if [[ $line == *"M/s"* ]] && [[ $line != *"DISK READ"* ]] && [[ $line != *"DISK WRITE"* ]]; then
HIGH_IO_PROCESSES=$((HIGH_IO_PROCESSES + 1))
fi
done < /tmp/iotop_tmp.log
if [ $HIGH_IO_PROCESSES -gt 0 ]; then
SUBJECT="I/O告警: 检测到高磁盘I/O活动"
MESSAGE="在 $(date) 检测到高磁盘I/O活动\n\n详细报告:\n$(cat /tmp/iotop_tmp.log | head -20)"
echo -e "$MESSAGE" >> $LOG_FILE
echo -e "$MESSAGE" | mail -s "$SUBJECT" $ALERT_EMAIL
echo "$(date): 检测到高I/O活动,已发送告警邮件" >> $LOG_FILE
else
echo "$(date): I/O活动正常" >> $LOG_FILE
fi
# 清理临时文件
rm -f /tmp/iotop_tmp.log