项目地址:https://github.com/shzstone/IOWatch
📝 内容摘要
你的 NAS 或 OpenWrt 硬盘是否总是莫名其妙地自动启动?明明没有人在读写,硬盘却频繁“唤醒”?iowatch 是一款不到 1MB、零依赖的 C 语言极致轻量工具。它利用 Linux 内核的 fanotify 机制,能精准捕捉并告诉你:“谁”在“什么时候”读写了“哪个文件”。
它是分析磁盘休眠问题的终极方案,完美支持 ARM (群晖/绿联/极空间)、x86 (服务器) 及 OpenWrt 环境。
🔍 痛点:为什么硬盘不休眠?
如果你拥有一台 NAS 或运行 OpenWrt 的路由器,你一定经历过这种困扰:
- 明明设置了 15 分钟硬盘休眠,但总能听到硬盘发出“咔哒”一声重新转起来。
- 传统的 iotop 只能看到实时的吞吐量,对这种瞬时且零星的“偷跑”访问无能为力。
- lsof 只能看到当前打开的文件,却无法记录过去那一秒发生的读写动作。
iowatch 诞生了。 它像哨兵一样守在文件系统的挂载点,记录底层的每一丝动静。
✨ 核心特性
- 零依赖运行:采用静态编译(Static Linking),生成后的单个二进制文件不依赖任何系统库(如 GLIBC),真正做到拷贝即用。
- 极低系统开销:基于内核 fanotify 子系统,由内核事件驱动,不轮询、不占 CPU。
- 全架构支持:源码可编译于 ARM64/AArch64 (现代 NAS)、x86_64 (普通服务器) 甚至 MIPS (老旧路由器)。
- 精准关联进程:不仅显示进程 ID(PID)和进程名,还能通过 /proc 接口追溯触发事件的原始执行程序路径,即使是 Docker 容器内的进程也难逃法网。
- 输出简洁直观:移除一切冗余,只保留时间戳、动作类型(OPEN/READ/WRITE)、PID、进程名和完整路径。
🛠️ 作用与实战:如何利用 iowatch 找回休眠?
iowatch 在你的“磁盘休眠保卫战”中扮演着侦察兵的角色:
- 识别“心跳”进程:许多服务(如 smartd)会定期轮询读取磁盘状态。通过 iowatch 的时间戳,你可以发现这些规律性的访问。
- 锁定“隐形”写入:系统日志(rsyslog)或容器缓存的每一次 WRITE_CLOSE 动作都会强制内核刷盘(Sync),唤醒磁盘。
- 穿透容器迷雾:在 Docker 环境下,单纯看进程名(如 python)很难判断归属。iowatch 会显示程序的执行路径,帮你直接锁定是哪个容器在搞鬼。
🚀 编译与部署指南
1. 安装编译器 (GCC)
在你的目标机器(NAS 或路由器)上安装 GCC:
- Debian/Ubuntu/宿主机: sudo apt install -y gcc libc6-dev
- OpenWrt: opkg update && opkg install gcc libc-dev
2. 静态编译 (跨版本运行的关键)
# 从 GitHub 克隆源码
git clone https://github.com/guoshh1978/IOWatch.git
cd IOWatch
# 执行静态编译,生成独立运行文件
gcc -O3 -static iowatch_clean.c -o iowatch3. 运行与分析
首先运行 df -h 找到你想要监控的硬盘挂载点(例如 /volume1)。
# 启动监控
sudo ./iowatch /volume1输出示例:
2024-04-01 13:08:45 | READ | 1245 | python3 | /volume1/data/config.json [/usr/bin/python3]
2024-04-01 13:08:50 | MODIFY | 890 | smbd | /volume1/share/log.txt [/usr/sbin/smbd]⚠️ 兼容性注意事项
此工具默认使用 FAN_MARK_FILESYSTEM 标志(内核 5.1+ 支持)。
如果你的设备内核版本较低(可通过 uname -r 查看),请在源码中做如下简单替换:
- 将 FAN_MARK_FILESYSTEM 替换为 FAN_MARK_MOUNT。
提示: 使用 FAN_MARK_MOUNT 时,输入的路径必须是 df 命令中显示的挂载点根路径(如 /mnt/sda1),否则会报错。
💡 结语
磁盘休眠不仅是为了省那几块钱电费,更是为了延长机械硬盘的寿命。希望 iowatch 能够帮你彻底扫清那些阻碍休眠的后台阴影,让你的 NAS 真正安静下来。
分类: 操作系统 / 运维 / NAS & 嵌入式
标签: #fanotify #硬盘休眠 #IO监控 #C语言 #NAS运维 #OpenWrt


