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
이 문제를 어떻게 처리해야 합니까?
내가 보는 유일한 공통 스레드는 events 입니다 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<>+'