
我想使用 來監視文件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<>+'