gopsutil disk与load包详解:磁盘分区、IO计数器、系统负载一次看全
【免费下载链接】gopsutilpsutil for golang项目地址: https://gitcode.com/gh_mirrors/go/gopsutil
想在 Go 程序里监控磁盘空间、磁盘IO和系统负载?gopsutil(Go 版 psutil)的disk包和load包就是为此而生的:disk.Usage()查磁盘使用率,disk.Partitions()枚举分区,disk.IOCounters()拿 IO 计数器,load.Avg()读 1/5/15 分钟负载。本文带你快速上手这两个包,一次搞懂所有核心指标。
📦 快速安装与目录结构
一行命令引入依赖(v4 是最新大版本):
go get github.com/shirou/gopsutil/v4两个包都放在独立目录,按操作系统拆分实现文件,这是 gopsutil 跨平台的经典写法:
| 包 | 公共定义 | Linux 实现 | 说明 |
|---|---|---|---|
disk | disk/disk.go | disk/disk_linux.go | 磁盘用量、分区、IO 计数器 |
load | load/load.go | load/load_linux.go | 平均负载、进程统计 |
💾 disk 包:磁盘监控的三大武器
disk包的对外 API 集中在 disk/disk.go 中,共 5 个函数:Usage、Partitions、IOCounters、SerialNumber、Label。
1. 磁盘空间使用率:disk.Usage()
Usage(path)接受文件系统路径(如"/"或C:),返回 UsageStat 结构体:
Total/Free/Used:总容量、空闲、已用(字节)UsedPercent:使用率百分比InodesTotal/InodesUsed/InodesFree:inode三元组(新手容易忽略!inode 耗尽时即使磁盘还有空间也会No space left on device)Fstype:文件系统类型,如ext4
v, err := disk.Usage("/") fmt.Printf("Total: %v, Free: %v, UsedPercent: %.1f%%\n", v.Total, v.Free, v.UsedPercent)⚠️ 传参注意:要传挂载点(
"/"),而不是设备名(/dev/vda1),见 disk.go 的注释说明。
2. 枚举磁盘分区:disk.Partitions()
Partitions(all)返回 PartitionStat 列表,每项包含Device(设备)、Mountpoint(挂载点)、Fstype(文件系统类型)、Opts(挂载选项,如ro/rw)。
all参数的含义:
false(默认):只返回真实物理设备(硬盘、U 盘、光驱),过滤掉/dev/shm、proc等虚拟文件系统true:返回所有挂载项
Linux 实现读取/proc/1/mountinfo(旧内核自动回退mounts),并处理了 bind mount、/dev/mapper符号链接解析、NVMe 命名归一化等细节,见 disk_linux.go。
parts, err := disk.Partitions(false) for _, p := range parts { fmt.Println(p.Device, p.Mountpoint, p.Fstype, strings.Join(p.Opts, ",")) }3. 磁盘 IO 计数器:disk.IOCounters()
IOCounters(names...)返回map[设备名]IOCountersStat,不传参数则统计所有磁盘。IOCountersStat 是排查"磁盘瓶颈"的黄金指标集:
| 字段 | 含义 |
|---|---|
ReadCount/WriteCount | 读/写操作次数(IOPS 基数) |
MergedReadCount/MergedWriteCount | 合并后的操作次数(相邻 IO 合并,越小说明随机写越少) |
ReadBytes/WriteBytes | 读/写字节数(吞吐量基数) |
ReadTime/WriteTime | 读/写耗时(毫秒,可用于算平均延迟) |
IopsInProgress | 当前正在进行的 IO 数 |
IoTime/WeightedIO | IO 占用时间 / 加权 IO 时间(算磁盘利用率的利器) |
Name/SerialNumber/Label | 设备名、序列号、卷标签(Linux 特有,序列号取自 udev,见 disk_linux.go) |
监控场景的常见用法是两次采样求差值:间隔 1 秒调用两次IOCounters(),用(本次 - 上次) / 1得到每秒的读写字节数和 IOPS,这就是 Prometheus 等监控系统的工作原理。
💡 小技巧:传入设备名可以只查指定磁盘,如
disk.IOCounters("sda"),支持传/dev/sda或sda两种写法。
4. 附加功能:序列号与卷标签
SerialNumber("/dev/sda"):获取物理设备序列号(先查 udev 数据,再回退 sysfs 的model+serial)Label("/dev/sda"):获取 devicemapper 名或 udev 卷标签
适合做硬件资产盘点,实现细节见 disk_linux.go。
📈 load 包:读懂系统负载
load包只有两个函数,API 定义在 load/load.go。
1. 平均负载:load.Avg()
Avg()返回 AvgStat:Load1、Load5、Load15,对应top/uptime显示的 1、5、15 分钟平均负载——系统上平均每分钟处于"可运行+不可中断"状态的任务数。
Linux 实现优先读/proc/loadavg,失败时回退到sysinfo系统调用(位运算还原负载值),见 load_linux.go;macOS 则通过sysctl("vm.loadavg")读取,见 load_darwin.go。
avg, err := load.Avg() fmt.Printf("Load1: %.2f, Load5: %.2f, Load15: %.2f\n", avg.Load1, avg.Load5, avg.Load15)📌 经验法则:负载值 ≈ CPU 核心数时算满载;Load1 持续明显高于核心数,说明系统在排队等待,该扩容或查慢任务了。
2. 主机级杂项统计:load.Misc()
Misc()返回 MiscStat:
ProcsTotal:当前进程总数ProcsCreated:系统启动以来创建的进程数ProcsRunning:正在运行的进程数ProcsBlocked:因等待 IO 而阻塞的进程数Ctxt:上下文切换次数(两次采样求差值可观察调度压力)
Linux 版从/proc/stat逐行解析得到这些值,见 load_linux.go;macOS 版改用ps axo state命令统计,见 load_darwin.go。
🌐 跨平台支持一览
gopsutil 全程不用 cgo,把 C 结构体移植成 Go 结构体。两个包的平台覆盖情况:
| 功能 | Linux | macOS | Windows | FreeBSD | OpenBSD |
|---|---|---|---|---|---|
| disk.Usage | ✅ | ✅ | ✅ | ✅ | ✅ |
| disk.Partitions | ✅ | ✅ | ✅ | ✅ | ✅ |
| disk.IOCounters | ✅ | ✅ | ✅ | ✅ | ✅ |
| disk.SerialNumber / Label | ✅ | — | — | — | — |
| load.Avg | ✅ | ✅ | ✅ | ✅ | ✅ |
| load.Misc | ✅ | ✅ | ✅ | ✅ | — |
各平台实现文件命名规律为disk_<系统>.go/load_<系统>.go,如 disk/disk_windows.go(Windows 通过GetDiskFreeSpaceExW、DISK_PERFORMANCE等 API 实现)、disk/disk_darwin.go(getfsstat系统调用)。
🧪 动手验证:跑一下测试
仓库自带完善的测试用例,不用自己造轮子:
- disk/disk_test.go:
TestUsage、TestPartitions、TestIOCounters各平台的通用测试 - load/load_test.go:
TestAvg、TestMisc及基准测试 - disk/disk_linux_test.go:基于
testdata/下/proc快照的 Linux 专项测试
在你的项目里执行go test ./...(或在仓库目录执行)即可验证功能可用。
🎯 小结:一份速查清单
| 需求 | 调用 | 关键返回值 |
|---|---|---|
| 磁盘还剩多少空间 | disk.Usage("/") | UsedPercent、Free、InodesFree |
| 列出所有挂载的磁盘 | disk.Partitions(false) | Device、Mountpoint、Fstype |
| 磁盘读写吞吐与 IOPS | disk.IOCounters() | ReadBytes、WriteBytes、ReadCount、IoTime |
| 磁盘序列号/标签 | disk.SerialNumber()/disk.Label() | 设备序列号、卷标签 |
| 系统负载 | load.Avg() | Load1、Load5、Load15 |
| 进程数与上下文切换 | load.Misc() | ProcsRunning、ProcsBlocked、Ctxt |
记住两个核心习惯:IO 指标要两次采样求差值才有"每秒"意义;磁盘空间告警别忘看 inode。掌握以上内容,你就能用 gopsutil 的disk与load包写出覆盖磁盘与负载监控的完整 Go 监控程序了 🚀
【免费下载链接】gopsutilpsutil for golang项目地址: https://gitcode.com/gh_mirrors/go/gopsutil
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考