inotify监控普通文件仅能检测到首次变更的问题求助
问题原因
1. 代码存在逻辑错误
你声明的变量i仅在main函数入口处初始化为0,第一次读取完inotify事件后,i的值已经累加等于第一次的length,后续进入外层循环时不会重置i的值,因此内层while(i < length)的遍历逻辑永远不会执行,你自然看不到后续的事件输出。
2. 编辑器保存策略导致监听失效
从你提供的inotifywait输出可以看到明确的DELETE_SELF事件,说明你使用的编辑器修改文件后保存时,不是直接修改原文件的内容,而是采用了「删除原文件+新建同名文件写入新内容」的策略:
- inotify的监听是绑定到文件inode的,不是绑定到文件路径的,原文件被删除后,你之前添加的监听会自动失效
- 后续你修改的是新创建的同名文件,没有对应的监听规则,因此程序会一直阻塞在
read()调用上,没有事件返回。
修复方案
第一步:修复代码逻辑
把变量i的初始化放到外层while(1)循环内部,保证每次读取新的事件队列时,都从缓冲区起始位置开始遍历:
while(1) { int i = 0; // 每次读取事件前重置i length = read(fd, buffer, BUF_LEN); if (length < 0) { perror("read"); } while (i < length) { struct inotify_event* event = (struct inotify_event*) &buffer[i]; // 此处可新增判断IN_DELETE_SELF事件的逻辑,用于后续重新添加监听 if (event->len) { if (event->mask & IN_MODIFY) { printf("The file %s was modified.\n", event->name); } } i += EVENT_SIZE + event->len; } }
第二步:适配文件删除重建的场景
你可以二选一实现:
- 方案A(适配所有编辑场景):改为监听文件所在的目录,新增对
IN_CREATE、IN_MOVED_TO事件的监听,当检测到目标文件名的文件被创建/移动到目录时,先移除旧的监听,再为新的同名文件添加监听即可。 - 方案B(临时测试用):修改编辑器配置,关闭写时替换的逻辑。例如vim可以在配置中添加
set backupcopy=yes,保存时会直接写入原文件,不会触发删除重建。
验证方法
你可以先不用编辑器修改文件,直接用命令echo "test content" >> /path/to/my/file.txt追加内容,这种方式是直接修改原文件,不会触发删除重建,如果此时程序能正常检测到多次修改,就说明问题确实是编辑器保存策略导致的。
内容的提问来源于stack exchange,提问作者userr019283
相关产品推荐
相关产品推荐

