inotify を使用して編集されたファイルの監視を確実に維持するにはどうすればよいですか?

inotify を使用して編集されたファイルの監視を確実に維持するにはどうすればよいですか?

でファイルを監視しinotify、誰かがコンテンツ (IN_MODIFYまたはIN_CLOSE_WRITE) を変更したときに何らかのコードをトリガーしたいのですが、ユーザーがお気に入りのツールでファイルを編集したときに がイベントを返さなくなるという問題が発生していますinotify。ファイルは単純なもの (1 行、スペースなし、最大 20 文字) です。使用を制限したくないのですが、さまざまな状況に対処する方法がわかりません。

私が使用しているのinotifyは、さまざまなアプリケーションがファイルを編集するときに受け取るイベントです。

アクション inotify イベント
touch file IN_OPEN
echo "data" > file IN_MODIFYIN_OPENIN_ACCESS、 それからIN_CLOSE_NOWRITE
nano file(オープン時) IN_OPEN
nano file(の上^O IN_MODIFY、、、IN_CLOSE_WRITEIN_OPENIN_ACCESS
vim file(オープン時) IN_OPENIN_CLOSE_NOWRITE
vim file(の上:w IN_MOVE_SELF、、IN_ATTRIBこのファイルからのイベントは停止します
gedit file(オープン時) IN_OPEN、、IN_CLOSE_NOWRITEIN_ACCESS
gedit file(保存時) IN_OPEN、、、このファイルからのイベントは停止しIN_CLOSE_WRITEますIN_ATTRIB
mv newfile file IN_ATTRIBすると、このファイルからのイベントは停止します

geditある時点で、トリガーもトリガーされてから静かになったように見えましたIN_DELETE_SELF

vimユーザーがとを使用する場合、ユーザーが編集を完了するとイベントのgedit取得が停止します。これにはどのように対処すればよいでしょうか?inotify

共通しているのはイベントだけです。イベントを受け取ったら、を実行し、同じパスに基づいて新しい を再作成する必要があるのではないIN_ATTRIBかと思います。しかし、それが正しいアプローチでしょうか?IN_ATTRIBinotify_rm_watch()wdinotify_add_watch()

もう 1 つのオプションは、親ディレクトリを監視することです。影響を受けるファイル名は に含まれているためinotify_event::name、対象のファイルでフィルター処理し、 が対象のファイルに一致する場合、IN_MODIFYまたはをトリガーできます。IN_CLOSE_WRITEname

答え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上で試したテクニック ( touchecho "" >、、) をキャプチャします。これらを使用して、変更されたシンボリック リンクもキャプチャできると思います。vimnanogedit

答え2

または、非常に高速で、そのような問題がない fatrace を使用することもできます。たとえば、次のようになります。

fatrace --timestamp --filter='WD<>+'

関連情報