监控磁盘IO的脚本如何编写

wen 实用脚本 2

本文目录导读:

监控磁盘IO的脚本如何编写

  1. 使用 iostat 命令(推荐)
  2. 使用 /proc/diskstats 直接读取
  3. 带告警功能的监控脚本
  4. 使用 systemd 服务监控
  5. Python 版本的监控脚本
  6. 使用示例
  7. 监控指标说明

我来介绍几种监控磁盘IO的脚本方法:

使用 iostat 命令(推荐)

基础监控脚本

#!/bin/bash
# 监控磁盘IO的脚本
INTERVAL=1  # 监控间隔(秒)
COUNT=10    # 监控次数
echo "时间,设备,读请求/s,写请求/s,读KB/s,写KB/s,IO等待时间(ms),IO利用率%"
for ((i=1; i<=$COUNT; i++))
do
    iostat -x 1 1 | tail -n +4 | while read line
    do
        if [[ $line =~ ^sd[a-z]|^nvme[0-9]|^vd[a-z] ]]; then
            device=$(echo $line | awk '{print $1}')
            rps=$(echo $line | awk '{print $4}')    # 每秒读请求数
            wps=$(echo $line | awk '{print $5}')    # 每秒写请求数
            rKB=$(echo $line | awk '{print $6}')   # 每秒读KB
            wKB=$(echo $line | awk '{print $7}')   # 每秒写KB
            await=$(echo $line | awk '{print $10}') # IO等待时间
            util=$(echo $line | awk '{print $12}')  # IO利用率
            echo "$(date +%H:%M:%S),$device,$rps,$wps,$rKB,$wKB,$await,$util%"
        fi
    done
    sleep $INTERVAL
done

使用 /proc/diskstats 直接读取

#!/bin/bash
# 直接读取/proc/diskstats监控磁盘IO
MONITOR_DEVICE="sda"  # 要监控的设备
INTERVAL=1
# 获取初始数据
get_disk_stats() {
    local device=$1
    cat /proc/diskstats | grep "$device " | head -1 | awk '{print $4,$5,$6,$7,$8,$9,$10}'
}
# 计算IO指标
calc_io_metrics() {
    local device=$1
    # 获取前后两次数据
    local stats1=($(get_disk_stats $device))
    sleep $INTERVAL
    local stats2=($(get_disk_stats $device))
    # 计算差值
    local read_completed=$(( ${stats2[0]} - ${stats1[0]} ))
    local read_merged=$(( ${stats2[1]} - ${stats1[1]} ))
    local read_sectors=$(( ${stats2[2]} - ${stats1[2]} ))
    local read_time=$(( ${stats2[3]} - ${stats1[3]} ))
    local write_completed=$(( ${stats2[4]} - ${stats1[4]} ))
    local write_merged=$(( ${stats2[5]} - ${stats1[5]} ))
    local write_sectors=$(( ${stats2[6]} - ${stats1[6]} ))
    local write_time=$(( ${stats2[7]} - ${stats1[7]} ))
    # 计算IOPS和吞吐量
    local read_iops=$(( read_completed / $INTERVAL ))
    local write_iops=$(( write_completed / $INTERVAL ))
    local read_kbs=$(( read_sectors * 512 / 1024 / $INTERVAL ))
    local write_kbs=$(( write_sectors * 512 / 1024 / $INTERVAL ))
    echo "$(date +%H:%M:%S) $device 读IOPS:$read_iops 写IOPS:$write_iops 读KB/s:$read_kbs 写KB/s:$write_kbs"
}
echo "开始监控磁盘IO..."
while true; do
    calc_io_metrics $MONITOR_DEVICE
done

带告警功能的监控脚本

#!/bin/bash
# 配置参数
DEVICE="sda"
THRESHOLD_IOPS=1000    # IOPS阈值
THRESHOLD_UTIL=90      # 磁盘利用率阈值(%)
THRESHOLD_AWAIT=100    # IO等待时间阈值(ms)
LOG_FILE="/var/log/disk_io_monitor.log"
ALERT_EMAIL="admin@example.com"
# 日志函数
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}
# 告警函数
send_alert() {
    local message=$1
    echo "$message" | mail -s "磁盘IO告警 - $DEVICE" $ALERT_EMAIL
    log_message "告警: $message"
}
# 监控主循环
monitor_disk_io() {
    while true; do
        # 获取IO统计信息
        IO_STATS=$(iostat -x $DEVICE 1 1 | tail -1)
        # 提取各项指标
        UTIL=$(echo $IO_STATS | awk '{print $12}')
        AWAIT=$(echo $IO_STATS | awk '{print $10}')
        R_IOPS=$(echo $IO_STATS | awk '{print $4}')
        W_IOPS=$(echo $IO_STATS | awk '{print $5}')
        TOTAL_IOPS=$(echo "$R_IOPS + $W_IOPS" | bc)
        # 记录日志
        log_message "设备: $DEVICE, 利用率: ${UTIL}%, 等待时间: ${AWAIT}ms, IOPS: ${TOTAL_IOPS}"
        # 检查阈值并告警
        if (( $(echo "$UTIL > $THRESHOLD_UTIL" | bc -l) )); then
            send_alert "磁盘利用率过高: ${UTIL}% (阈值: ${THRESHOLD_UTIL}%)"
        fi
        if (( $(echo "$TOTAL_IOPS > $THRESHOLD_IOPS" | bc -l) )); then
            send_alert "IOPS过高: ${TOTAL_IOPS} (阈值: ${THRESHOLD_IOPS})"
        fi
        if (( $(echo "$AWAIT > $THRESHOLD_AWAIT" | bc -l) )); then
            send_alert "IO等待时间过长: ${AWAIT}ms (阈值: ${THRESHOLD_AWAIT}ms)"
        fi
        sleep 5  # 每5秒检查一次
    done
}
# 启动监控
echo "启动磁盘IO监控..."
monitor_disk_io &

使用 systemd 服务监控

创建监控服务文件 /etc/systemd/system/disk-monitor.service

[Unit]
Description=Disk IO Monitor Service
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/disk_monitor.sh
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target

启用服务

chmod +x /usr/local/bin/disk_monitor.sh
systemctl daemon-reload
systemctl enable disk-monitor.service
systemctl start disk-monitor.service

Python 版本的监控脚本

#!/usr/bin/env python3
import time
import os
import sys
from datetime import datetime
def read_disk_stats(device):
    """读取磁盘统计信息"""
    try:
        with open('/proc/diskstats', 'r') as f:
            for line in f:
                fields = line.split()
                if fields[2] == device:
                    return {
                        'read_ios': int(fields[3]),
                        'read_merges': int(fields[4]),
                        'read_sectors': int(fields[5]),
                        'read_ticks': int(fields[6]),
                        'write_ios': int(fields[7]),
                        'write_merges': int(fields[8]),
                        'write_sectors': int(fields[9]),
                        'write_ticks': int(fields[10]),
                        'in_flight': int(fields[11]),
                        'io_ticks': int(fields[12]),
                        'time_in_queue': int(fields[13])
                    }
    except Exception as e:
        print(f"读取磁盘统计出错: {e}")
        return None
def calculate_io_rate(prev, curr, interval):
    """计算IO速率"""
    rate = {}
    for key in ['read_ios', 'write_ios', 'read_sectors', 'write_sectors']:
        if key in prev and key in curr:
            rate[key] = (curr[key] - prev[key]) / interval
    return rate
def main():
    device = sys.argv[1] if len(sys.argv) > 1 else 'sda'
    interval = int(sys.argv[2]) if len(sys.argv) > 2 else 1
    print(f"监控磁盘: {device}")
    print(f"{'时间':<20} {'读IOPS':<10} {'写IOPS':<10} {'读MB/s':<10} {'写MB/s':<10}")
    print("-" * 60)
    prev_stats = read_disk_stats(device)
    if not prev_stats:
        print(f"找不到设备 {device}")
        sys.exit(1)
    while True:
        time.sleep(interval)
        curr_stats = read_disk_stats(device)
        if curr_stats:
            rates = calculate_io_rate(prev_stats, curr_stats, interval)
            current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            read_iops = rates.get('read_ios', 0)
            write_iops = rates.get('write_ios', 0)
            read_mb = rates.get('read_sectors', 0) * 512 / 1024 / 1024
            write_mb = rates.get('write_sectors', 0) * 512 / 1024 / 1024
            print(f"{current_time:<20} {read_iops:<10.0f} {write_iops:<10.0f} {read_mb:<10.2f} {write_mb:<10.2f}")
            prev_stats = curr_stats
if __name__ == '__main__':
    main()

使用示例

# 运行基础监控脚本
chmod +x disk_monitor.sh
./disk_monitor.sh
# 运行Python版本
python3 disk_monitor.py sda 1

监控指标说明

  • IOPS: 每秒IO操作数
  • Throughput: 吞吐量 (KB/s)
  • await: IO等待时间 (ms)
  • util: 磁盘利用率 (%)
  • queue: IO队列长度

选择合适的脚本根据你的具体需求,如果是生产环境,建议使用iostat和系统自带的工具。

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