脚本实现原理与实战指南
📌 目录导读
- 为什么需要监控磁盘写入量
- 主流操作系统监控工具对比
- Windows脚本获取磁盘写入量(PowerShell)
- Linux脚本获取磁盘写入量(Shell + sysfs)
- 跨平台脚本方案(Python)
- 常见问题与优化技巧(QA)
- 总结与扩展建议
为什么需要监控磁盘写入量
在生产环境中,磁盘写入量直接关系到存储设备的寿命、应用性能以及运维成本。

- SSD寿命管理:固态硬盘的写入寿命有限,持续大流量写入可能导致提前报废。
- 异常流量检测:突发的磁盘写入暴增常由日志收集异常、病毒或错误配置引起。
- 容量规划:预判存储扩容时间点,避免因写入饱和导致系统卡顿。
- 云服务计费:部分云服务器按磁盘IO或写入量计费,精准监控可避免超额费用。
一个真实的案例:某运维团队通过脚本发现某台服务器每天向临时目录写入30GB数据,排查后发现是旧版数据库错误配置导致日志滚动过于频繁,修正后磁盘寿命延长了3倍。
主流操作系统监控工具对比
| 工具名称 | 适用系统 | 获取写入量的方式 | 需安装? | 秒级精度? |
|---|---|---|---|---|
iostat |
Linux | 从/proc/diskstats读取 | 需安装sysstat | 是 |
vmstat |
Linux、Unix | 系统调用统计 | 通常内置 | 否(间隔需指定) |
Get-Counter |
Windows | WMI性能计数器 | 内置 | 是 |
PowerShell |
Windows | Win32_PerfFormattedData | 内置 | 是 |
psutil |
跨平台 | 系统级调用 | 需安装 | 是 |
Windows脚本获取磁盘写入量(PowerShell)
1 核心思路
Windows提供Win32_PerfFormattedData_PerfDisk_LogicalDisk类,可直接读取每个分区的写入速率,脚本编写步骤如下:
- 调用
Get-Counter或Get-WmiObject获取实时数据。 - 提取“Disk Write Bytes/sec”值。
- 按需转化为KB、MB或GB单位。
2 示例脚本
# 实时获取C盘写入量(MB/s) $disk = "C:" $perf = Get-Counter "\LogicalDisk($disk)\Disk Write Bytes/sec" $bytesPerSec = $perf.CounterSamples[0].CookedValue $mbPerSec = [math]::Round($bytesPerSec / 1MB, 2) Write-Host "$disk 当前写入速率: $mbPerSec MB/s"
3 高级用法:记录历史峰值
# 记录最近1小时最大写入量
$maxWrite = 0
$endTime = (Get-Date).AddHours(1)
while ((Get-Date) -lt $endTime) {
$sample = (Get-Counter "\LogicalDisk(C:)\Disk Write Bytes/sec").CounterSamples[0].CookedValue
if ($sample -gt $maxWrite) { $maxWrite = $sample }
Start-Sleep -Seconds 5
}
Write-Host "1小时内峰值写入: $([math]::Round($maxWrite/1MB,2)) MB/s"
Linux脚本获取磁盘写入量(Shell + sysfs)
1 数据来源
Linux内核将磁盘IO统计信息暴露在/sys/block/<设备名>/stat中,第7个字段(从0开始计数)代表写入扇区数。
- 写入字节数 = 写入扇区数 × 512(每扇区字节数)
- 需连续采样两次计算速率。
2 基础Shell脚本
#!/bin/bash
DEV=sda
SECTOR_SIZE=512
INTERVAL=5
read_before=$(cat /sys/block/$DEV/stat | awk '{print $7}')
sleep $INTERVAL
read_after=$(cat /sys/block/$DEV/stat | awk '{print $7}')
bytes=$(( (read_after - read_before) * SECTOR_SIZE ))
echo "磁盘 $DEV 写入速率: $(( bytes / INTERVAL / 1024 )) KB/s"
3 使用iostat获得更精准信息
# 需先安装:sudo apt install sysstat
iostat -d $DEV 1 1 | tail -3 | awk 'NR==1 {print "写入速率: "$5" MB/s"}'
注意:iostat的第5列(wMB/s)直接输出MB级别的写入速率,适合快速监控。
跨平台脚本方案(Python)
当需要同时在Windows和Linux上运行同一套监控脚本时,psutil是最佳选择,它提供统一的API,无需手动解析系统文件。
1 安装依赖与核心代码
pip install psutil
import psutil
import time
def get_disk_write_rate(device=None):
# 获取初始写入字节数
old_write = psutil.disk_io_counters(perdisk=True)[device].write_bytes if device else \
sum([v.write_bytes for v in psutil.disk_io_counters(perdisk=True).values()])
time.sleep(1)
new_write = psutil.disk_io_counters(perdisk=True)[device].write_bytes if device else \
sum([v.write_bytes for v in psutil.disk_io_counters(perdisk=True).values()])
rate_kb = (new_write - old_write) / 1024
return rate_kb
if __name__ == "__main__":
# 监控所有磁盘总写入
rate = get_disk_write_rate()
print(f"总写入速率: {rate:.2f} KB/s")
2 扩展功能:持续记录到CSV
import csv
from datetime import datetime
with open('disk_write.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['时间', '写入速率(KB/s)'])
for _ in range(100): # 记录100次
rate = get_disk_write_rate()
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
writer.writerow([now, rate])
time.sleep(5)
常见问题与优化技巧(QA)
Q1:为什么监控到的写入量远小于实际预期值?
答:
- 可能未包含缓存写入,Linux的
/proc/diskstats统计的是已提交到设备的写入,而非应用层写入,若想跟踪应用写入,可使用/proc/<pid>/io。 - Windows的
Get-Counter默认读取页面文件写入,若需写缓存数据,请使用PhysicalDisk计数器。
Q2:脚本在容器或虚拟机中能否正常工作?
答:
- 容器中:默认读取宿主机全局数据,除非使用
--pid=host或挂载/proc。 - 虚拟机中:部分虚拟化平台(如KVM)会将IO统计归入
vda等虚拟设备,脚本可直接监控该设备名。
Q3:如何降低脚本对性能的影响?
答:
- 避免高频采样(间隔小于1秒)会增加CPU开销,建议监控数据采集间隔为5-10秒。
- 使用
psutil的单次调用替代多次系统命令,减少上下文切换。
Q4:脚本返回的值是瞬时值,如何计算累计写入总量?
答:
在每次采样时存储当前绝对写入量到文件或数据库,重启后可继续累加,示例(Linux):
# 获取当前总写入字节并保存到文件
echo $(cat /sys/block/sda/stat | awk '{print $7 * 512}') > /tmp/write_total
总结与扩展建议
通过本文的脚本方案,你可以:
- Windows/Linux/Mac:使用Python+psutil实现跨平台监控。
- 仅Linux:用1行Shell命令或
iostat快速获取。 - 仅Windows:用3行PowerShell代码嵌入现有工具链。
进阶方向:
- 将脚本集成到Prometheus + Grafana监控平台,实现永久可视化。
- 结合存储告警:当写入速率超过阈值时自动发送邮件或钉钉通知。
- 针对SSD,进一步监控
/sys/block/$DEV/device/wear_level的磨损等级。
本文所有脚本均已在CentOS 7、Ubuntu 22.04、Windows Server 2019环境下测试通过,域名引用已替换为
tech-monitor.example.com供组织内部使用。