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_OPENIN_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이 문제를 어떻게 처리해야 합니까?

내가 보는 유일한 공통 스레드는 events 입니다 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<>+'

관련 정보