本文目录导读:

我来介绍几种监控磁盘IO并记录的方法:
Linux Shell脚本(使用iostat)
#!/bin/bash
# 磁盘IO监控脚本
LOG_FILE="/var/log/disk_io_monitor.log"
INTERVAL=5 # 监控间隔(秒)
# 检查iostat是否安装
if ! command -v iostat &> /dev/null; then
echo "请安装sysstat包: sudo apt-get install sysstat (Ubuntu) 或 sudo yum install sysstat (CentOS)"
exit 1
fi
# 添加日志头
echo "时间戳,设备,读请求/s,写请求/s,读KB/s,写KB/s,磁盘利用率(%)" > $LOG_FILE
# 开始监控
while true; do
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
# 获取所有磁盘的IO统计,去掉标题行
iostat -x 1 2 | awk 'NR>3 && /^[a-z]/ && !/^loop/ && !/^dm-/' | while read line; do
DEVICE=$(echo $line | awk '{print $1}')
R_RQS=$(echo $line | awk '{print $4}')
W_RQS=$(echo $line | awk '{print $5}')
R_KB=$(echo $line | awk '{print $6}')
W_KB=$(echo $line | awk '{print $7}')
UTIL=$(echo $line | awk '{print $NF}')
echo "$TIMESTAMP,$DEVICE,$R_RQS,$W_RQS,$R_KB,$W_KB,$UTIL" >> $LOG_FILE
done
sleep $INTERVAL
done
Python脚本(更灵活的监控)
#!/usr/bin/env python3
"""
磁盘IO监控脚本 - 使用psutil库
安装: pip install psutil
"""
import psutil
import time
import csv
from datetime import datetime
import argparse
class DiskIOMonitor:
def __init__(self, interval=5, log_file="disk_io_log.csv", disk_name=None):
self.interval = interval
self.log_file = log_file
self.disk_name = disk_name
def get_disk_stats(self):
"""获取磁盘IO统计"""
disk_io = psutil.disk_io_counters(perdisk=True)
stats = {}
for disk_name, disk_data in disk_io.items():
# 过滤掉虚拟磁盘
if not any(x in disk_name for x in ['loop', 'dm-', 'ram']):
if self.disk_name and self.disk_name not in disk_name:
continue
stats[disk_name] = {
'read_count': disk_data.read_count,
'write_count': disk_data.write_count,
'read_bytes': disk_data.read_bytes,
'write_bytes': disk_data.write_bytes,
'read_time': disk_data.read_time,
'write_time': disk_data.write_time
}
return stats
def monitor(self):
"""开始监控"""
print(f"开始监控磁盘IO,日志文件: {self.log_file}")
print(f"监控间隔: {self.interval}秒")
# 初始化CSV文件
with open(self.log_file, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow([
'Timestamp', 'Disk',
'Read_Count', 'Write_Count',
'Read_MB', 'Write_MB',
'Read_MB_per_sec', 'Write_MB_per_sec',
'IO_PS'
])
# 获取初始值
prev_stats = self.get_disk_stats()
prev_time = time.time()
while True:
time.sleep(self.interval)
try:
current_stats = self.get_disk_stats()
current_time = time.time()
time_diff = current_time - prev_time
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(self.log_file, 'a', newline='') as f:
writer = csv.writer(f)
for disk_name, current_data in current_stats.items():
if disk_name in prev_stats:
# 计算差值
read_diff = current_data['read_count'] - prev_stats[disk_name]['read_count']
write_diff = current_data['write_count'] - prev_stats[disk_name]['write_count']
read_bytes_diff = current_data['read_bytes'] - prev_stats[disk_name]['read_bytes']
write_bytes_diff = current_data['write_bytes'] - prev_stats[disk_name]['write_bytes']
# 计算速率
read_mb_per_sec = (read_bytes_diff / 1024 / 1024) / time_diff
write_mb_per_sec = (write_bytes_diff / 1024 / 1024) / time_diff
io_ps = (read_diff + write_diff) / time_diff
# 写入日志
writer.writerow([
timestamp,
disk_name,
read_diff,
write_diff,
read_bytes_diff / 1024 / 1024, # MB
write_bytes_diff / 1024 / 1024, # MB
round(read_mb_per_sec, 2),
round(write_mb_per_sec, 2),
round(io_ps, 0)
])
prev_stats = current_stats
prev_time = current_time
except KeyboardInterrupt:
print("\n监控已停止")
break
except Exception as e:
print(f"错误: {e}")
def main():
parser = argparse.ArgumentParser(description='磁盘IO监控工具')
parser.add_argument('-i', '--interval', type=int, default=5,
help='监控间隔(秒),默认5秒')
parser.add_argument('-l', '--log', type=str, default='disk_io_log.csv',
help='日志文件路径')
parser.add_argument('-d', '--disk', type=str, default=None,
help='指定监控的磁盘名称,如sda')
args = parser.parse_args()
monitor = DiskIOMonitor(
interval=args.interval,
log_file=args.log,
disk_name=args.disk
)
monitor.monitor()
if __name__ == "__main__":
main()
简易Shell脚本(使用/proc/diskstats)
#!/bin/bash
# 使用 /proc/diskstats 监控磁盘IO
LOG_FILE="/tmp/disk_io_stats.log"
INTERVAL=5
# 获取磁盘列表(排除虚拟磁盘)
DISKS=$(lsblk -dn -o NAME | grep -v loop | grep -v dm-)
# 记录初始值
declare -A PREV_READ PREV_WRITE
for disk in $DISKS; do
PREV_READ[$disk]=$(cat /sys/block/$disk/stat | awk '{print $3}')
PREV_WRITE[$disk]=$(cat /sys/block/$disk/stat | awk '{print $7}')
done
echo "开始监控磁盘IO..."
echo "时间戳 磁盘 读请求/秒 写请求/秒" > $LOG_FILE
while true; do
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
for disk in $DISKS; do
CURRENT_READ=$(cat /sys/block/$disk/stat | awk '{print $3}')
CURRENT_WRITE=$(cat /sys/block/$disk/stat | awk '{print $7}')
READ_PS=$(( (CURRENT_READ - ${PREV_READ[$disk]}) / INTERVAL ))
WRITE_PS=$(( (CURRENT_WRITE - ${PREV_WRITE[$disk]}) / INTERVAL ))
echo "$TIMESTAMP $disk $READ_PS $WRITE_PS" >> $LOG_FILE
PREV_READ[$disk]=$CURRENT_READ
PREV_WRITE[$disk]=$CURRENT_WRITE
done
sleep $INTERVAL
done
使用方式
Shell脚本:
# 保存脚本并添加执行权限 chmod +x disk_io_monitor.sh # 前台运行 ./disk_io_monitor.sh # 后台运行 nohup ./disk_io_monitor.sh & # 查看日志 tail -f /var/log/disk_io_monitor.log
Python脚本:
# 安装依赖 pip install psutil # 基本使用 python3 disk_io_monitor.py # 指定间隔和日志文件 python3 disk_io_monitor.py -i 10 -l /var/log/disk_io.csv # 监控特定磁盘 python3 disk_io_monitor.py -d sda # 后台运行 nohup python3 disk_io_monitor.py &
输出示例
Python脚本生成的CSV日志:
Timestamp,Disk,Read_Count,Write_Count,Read_MB,Write_MB,Read_MB_per_sec,Write_MB_per_sec,IO_PS
2024-01-15 10:30:00,sda,120,85,5.2,3.8,1.04,0.76,41.0
2024-01-15 10:30:05,sda,145,92,6.1,4.2,1.22,0.84,47.4
这些脚本适合不同的使用场景,可以根据具体需求选择合适的方案。