不完全可靠——inotify仅监听in_access/in_modify等事件,无法识别触发进程,且对mmap、/proc/pid/fd绕过、rename替换等场景完全失效;审计级追踪须用ebpf挂钩sys_enter_read/write或kprobe。

Linux下用inotify监控文件读写是否可靠?
不完全可靠——inotify 只能监听“事件”,比如 IN_ACCESS(读)、IN_MODIFY(写),但它**无法区分是哪个进程触发的**,也无法捕获所有读操作(例如 mmap 后的内存访问、/proc/self/fd 下的绕过行为)。它适合轻量级通知,不适合审计级追踪。
-
inotify对单个文件监控需先inotify_add_watch(fd, path, IN_ACCESS | IN_MODIFY),但path必须存在且不可被替换(软链接目标变更、rename 覆盖会导致 watch 失效) - 读操作仅在
open()+read()或cat等典型路径下触发IN_ACCESS;用dd if=/proc/PID/fd/X或直接mmap()读取该文件,inotify完全静默 - 若文件被
mv替换(即 unlink + rename),旧 watch 自动失效,新文件需重新 add_watch
需要进程级溯源时该用什么?
必须上内核态或 eBPF。Linux 5.8+ 推荐用 bpftrace 或自定义 eBPF program 挂在 sys_enter_read/sys_enter_write 上,再过滤目标文件 inode。
- 先用
stat -c "%i" /path/to/file获取 inode 号(如123456) - 用
bpftrace快速验证:bpftrace -e 'tracepoint:syscalls:sys_enter_read { if (args->fd >= 0 && (pid == pid)) { printf("read on fd %d\n", args->fd); } }'——但这只是起点,真正要关联到具体文件,得结合struct file*或通过fd查/proc/PID/fd/ - 更稳妥的做法是挂
kprobe:do_iter_readv和kprobe:__vfs_write,从struct file*提取f_inode->i_ino做比对,避免用户态 fd 表竞争问题
为什么 strace 不适合长期监控?
strace -p PID -e trace=read,write 或 strace -f -e trace=read,write -o log.txt ./app 看起来简单,但实际部署中问题集中:
- 每秒数千次系统调用时,
strace自身开销可能吃掉 20%+ CPU,日志爆炸(一行一调用,不含上下文) - 无法跨进程:只跟踪指定 PID 及其子进程,如果文件被其他无关进程(如 cron、systemd-journald)读取,直接漏掉
-
read()调用成功不代表内容被应用逻辑使用;write()成功也不代表数据已落盘——它只反映 syscall 层行为
Windows 上等效方案是什么?
Windows 没有 inotify 替代品,得用 ReadDirectoryChangesW + FILE_NOTIFY_CHANGE_LAST_ACCESS,但同样不保证读操作上报,且需注意:
- 必须以
FILE_FLAG_BACKUP_SEMANTICS打开目录句柄,否则对文件本身调用会失败 -
FILE_NOTIFY_CHANGE_LAST_ACCESS在 NTFS 上默认禁用(因性能影响),需管理员执行:fsutil behavior set disablelastaccess 0
- 无法获取调用进程名,只能拿到线程 ID;想查进程得额外调用
OpenThread+GetProcessIdOfThread,但可能因权限不足失败
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











