怎样用脚本监控磁盘IO并记录?

wen 实用脚本 2

本文目录导读:

怎样用脚本监控磁盘IO并记录?

  1. Linux Shell脚本(使用iostat)
  2. Python脚本(更灵活的监控)
  3. 简易Shell脚本(使用/proc/diskstats)
  4. 使用方式
  5. 输出示例

我来介绍几种监控磁盘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

这些脚本适合不同的使用场景,可以根据具体需求选择合适的方案。

抱歉,评论功能暂时关闭!