
Ich möchte eine Datei mit überwachen inotify
und Code auslösen, wenn jemand den Inhalt ändert ( IN_MODIFY
oder IN_CLOSE_WRITE
), aber ich stoße auf Probleme, bei denen inotify
keine Ereignisse mehr zurückgegeben werden, wenn Benutzer die Datei mit ihrem bevorzugten Tool bearbeiten. Die Datei soll einfach sein (eine Zeile, keine Leerzeichen, maximal 20 Zeichen). Ich würde ihre Verwendung lieber nicht einschränken, bin mir aber nicht sicher, wie ich mit verschiedenen Situationen umgehen soll.
Ich verwende inotify
und dies sind die Ereignisse, die ich erhalte, wenn verschiedene Anwendungen die Datei bearbeiten:
Aktion | inotify-Ereignisse |
---|---|
touch file |
IN_OPEN |
echo "data" > file |
IN_MODIFY , IN_OPEN , IN_ACCESS , DannIN_CLOSE_NOWRITE |
nano file (beim Öffnen) |
IN_OPEN |
nano file (An ^O ) |
IN_MODIFY , IN_CLOSE_WRITE , IN_OPEN ,IN_ACCESS |
vim file (beim Öffnen) |
IN_OPEN ,IN_CLOSE_NOWRITE |
vim file (An :w ) |
IN_MOVE_SELF , IN_ATTRIB , dann kommen keine Ereignisse mehr aus dieser Datei |
gedit file (beim Öffnen) |
IN_OPEN , IN_CLOSE_NOWRITE ,IN_ACCESS |
gedit file (beim Speichern) |
IN_OPEN , IN_CLOSE_WRITE , IN_ATTRIB , dann kommen keine Ereignisse mehr aus dieser Datei |
mv newfile file |
IN_ATTRIB , dann kommen keine Ereignisse mehr aus dieser Datei |
An einem Punkt dachte ich, ich hätte gedit
den Auslöser und auch den Auslöser gesehen IN_DELETE_SELF
, bevor es still wurde.
Wenn ein Benutzer vim
und verwendet gedit
, erhalte ich keine inotify
Ereignisse mehr, nachdem der Benutzer die Änderungen abgeschlossen hat. Wie soll ich damit umgehen?
Das einzige Gemeinsame, das ich sehe, ist das IN_ATTRIB
Ereignis. Ich vermute, dass ich, wenn ich das Ereignis erhalte , dies IN_ATTRIB
tun und dann basierend auf demselben Pfad ein neues erstellen sollte . Aber ist das der richtige Ansatz?inotify_rm_watch()
wd
inotify_add_watch()
Eine andere Möglichkeit wäre, das übergeordnete Verzeichnis zu überwachen. Der betroffene Dateiname ist in enthalten , sodass ich nach der gewünschten Datei filtern und alle oder inotify_event::name
auslösen kann, bei denen die mit meiner gewünschten Datei übereinstimmt.IN_MODIFY
IN_CLOSE_WRITE
name
Antwort1
Wie ikkachu erwähnt, erstellen einige Editoren eine neue Datei und ersetzen dann die ursprüngliche, wobei der Inode geändert wird. Das bedeutet, dass alle Überwachungen des ursprünglichen Überwachungsdeskriptors ablaufen.
Die Antwort besteht darin, sich das übergeordnete Verzeichnis anzusehen und nach Änderungen an allen Dateien mit dem Zielnamen zu suchen. Etwa so:
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();
}
Diese Ereignisse ( IN_MODIFY|IN_CREATE|IN_CLOSE_WRITE
) erfassen die Techniken, die ich oben ausprobiert habe ( touch
, echo "" >
, vim
, nano
, gedit
). Ich wette, ich könnte damit auch geänderte symbolische Links erfassen.
Antwort2
Oder Sie könnten Fatrace verwenden, das viel schneller ist und keine derartigen Probleme hat, z. B. etwas in dieser Art:
fatrace --timestamp --filter='WD<>+'