我想使用 来监视文件inotify
,并在有人更改内容(IN_MODIFY
或)时触发一些代码,但是当用户使用他们喜欢的工具编辑文件时,IN_CLOSE_WRITE
我遇到了停止返回事件的问题。inotify
该文件应该很简单(单行、无空格、最多 20 个字符)。我不想限制它们的使用,但我不确定如何处理不同的情况。
我正在使用inotify
这些是当各种应用程序编辑文件时我收到的事件:
行动 | inotify 事件 |
---|---|
touch file |
IN_OPEN |
echo "data" > file |
IN_MODIFY ,IN_OPEN ,IN_ACCESS , 然后IN_CLOSE_NOWRITE |
nano file (打开时) |
IN_OPEN |
nano file (在^O ) |
IN_MODIFY , IN_CLOSE_WRITE , IN_OPEN ,IN_ACCESS |
vim file (打开时) |
IN_OPEN ,IN_CLOSE_NOWRITE |
vim file (在:w ) |
IN_MOVE_SELF , IN_ATTRIB , 然后事件停止来自该文件 |
gedit file (打开时) |
IN_OPEN ,,IN_CLOSE_NOWRITE IN_ACCESS |
gedit file (保存时) |
IN_OPEN , IN_CLOSE_WRITE , IN_ATTRIB ,然后事件停止来自该文件 |
mv newfile file |
IN_ATTRIB ,然后事件停止来自该文件 |
有一次,我以为我看到了gedit
触发器,IN_DELETE_SELF
然后又沉默了。
vim
在用户使用and的情况下gedit
,我会inotify
在用户完成编辑后停止获取事件。我该如何处理这个问题?
我所看到的唯一共同点是事件IN_ATTRIB
。我怀疑当我收到事件时IN_ATTRIB
,我应该inotify_rm_watch()
这样做,然后基于相同的路径wd
重新创建一个新的。inotify_add_watch()
但这是正确的方法吗?
另一种选择可能是监视父目录。受影响的文件名包含在 中inotify_event::name
,因此我可以过滤感兴趣的文件,并触发任何IN_MODIFY
与我感兴趣的文件匹配的IN_CLOSE_WRITE
位置。name
答案1
正如 ikkachu 提到的,一些编辑器创建一个新文件,然后替换原始文件,更改 inode。这意味着原始监视描述符上的任何监视都将过期。
答案是查看父目录,并检查具有目标名称的任何文件的更改。像这样的东西:
namespace fs = std::filesystem;
fs::path path = "./file1";
assert( !path.is_directory() );
int fd = inotify_init();
int wd = inotify_add_watch(
fd,
path.parent_path().c_str(),
IN_MODIFY | IN_CREATE | IN_CLOSE_WRITE
);
...
inotify_event event;
read(fd, &event, BUF_SIZE);
if (wd == event->wd && path.filename() == event->name) {
emit_file_changed();
}
这些事件 ( IN_MODIFY|IN_CREATE|IN_CLOSE_WRITE
) 捕获了我在上面尝试过的技术 ( touch
, echo "" >
, vim
, nano
, gedit
)。我打赌我也可以捕获这些改变的符号链接。
答案2
或者您可以使用 fatrace,它速度快得多并且没有此类问题,例如:
fatrace --timestamp --filter='WD<>+'