inotify를 사용하여 편집된 파일에 대한 감시를 안정적으로 유지하는 방법은 무엇입니까?

inotify를 사용하여 편집된 파일에 대한 감시를 안정적으로 유지하는 방법은 무엇입니까?

inotify를 사용하여 파일을 모니터링 하고 누군가 콘텐츠( IN_MODIFY또는 )를 변경할 때 일부 코드를 트리거 하고 싶지만 사용자가 즐겨 사용하는 도구를 사용하여 파일을 편집하면 이벤트 반환이 중지되는 IN_CLOSE_WRITE문제가 발생합니다 . inotify파일은 단순해야 합니다(한 줄, 공백 없음, 최대 20자). 사용을 제한하고 싶지 않지만 다양한 상황을 처리하는 방법을 잘 모르겠습니다.

제가 사용하고 있는 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사용자가 및 를 사용하는 경우 사용자가 편집을 마친 후에는 이벤트 gedit수신이 중지됩니다 . inotify이 문제를 어떻게 처리해야 합니까?

제가 보는 공통점은 바로 이벤트 입니다 IN_ATTRIB. 나는 이벤트를 받으면 해당 경로를 기반으로 새 이벤트를 다시 생성해야 한다고 IN_ATTRIB생각 합니다. 그러나 그것이 올바른 접근 방식입니까?inotify_rm_watch()wdinotify_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<>+'

관련 정보