本文目录导读:

我来介绍几种监控磁盘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和系统自带的工具。