inotify 이벤트를 사용하여 변경 사항이있는 파일을보고 있습니다 (파이썬에서 libc로 호출).
동안 일부 파일의 경우 git clone
I는 다음을 참조하십시오, 나는 이상한 것을 볼 IN_CREATE
이벤트를, 그리고 통해 내가 볼 ls
파일 내용을 가지고,하지만, 내가 볼 수 없습니다 IN_MODIFY
또는 IN_CLOSE_WRITE
. IN_CLOSE_WRITE
파일에 응답하고 싶습니다 . 특히 파일 내용의 업로드를 시작하기 때문에 문제가 발생 합니다.
이상하게 동작하는 파일은 .git/objects/pack
디렉토리에 있으며 .pack
또는로 끝납니다 .idx
. git이 생성하는 다른 파일에는보다 규칙적인 IN_CREATE
-> IN_MODIFY
-> IN_CLOSE_WRITE
체인이 있습니다 ( IN_OPEN
이벤트를 보고 있지 않습니다 ).
이것은 MacOS의 도커 내부에 있지만 원격 시스템의 Linux의 도커에서도 동일한 증거를 보았으므로 MacOS 측면과 관련이 없다는 의혹이 있습니다. 보고 있고 동일한 도커 컨테이너 git clone
에 있으면 이것을보고 있습니다.
내 질문 :
-
이러한 파일에서 이러한 이벤트가 누락 된 이유는 무엇입니까?
-
그것에 대해 무엇을 할 수 있습니까? 특히,이 파일에 대한 쓰기 완료에 어떻게 응답합니까? 참고 : 이상적으로 “미완성”작문을 불필요하게 / (올바르게) 업로드하지 않도록 쓰기가 “완료”되었을 때 응답하고 싶습니다.
편집 : https://developer.ibm.com/tutorials/l-inotify/를 읽으면 내가보고있는 것과 일치하는 것처럼 보입니다.
- 와 같은 이름을 가진 별도의 임시 파일
tmp_pack_hBV4Alz
이 작성, 수정 및 닫힙니다. - 최종 이름 으로이 파일에 대한 하드 링크가 작성됩니다
.pack
. - 원래
tmp_pack_hBV4Alz
이름이 삭제됩니다.
파일을 업로드하는 트리거로 inotify를 사용하려고하는 내 문제가 .pack
파일이 다른 파일에 대한 하드 링크 임을 인식 하고이 경우 업로드하는 것으로 줄어 듭니다 .
답변
git
Linux 4.19.95 에서 2.24.1에 대해 별도로 질문에 대답하려면 다음을 수행하십시오 .
- 이러한 파일에서 이러한 이벤트가 누락 된 이유는 무엇입니까?
디렉토리 아래의 파일에 대해 항상 하드 링크를 사용하려고하기 때문에 IN_MODIFY
/ IN_CLOSE_WRITE
이벤트 가 표시되지 않습니다 . 네트워크 또는 파일 시스템 경계를 통해 복제하면 이러한 이벤트가 다시 나타납니다.git clone
.git/objects
- 그것에 대해 무엇을 할 수 있습니까? 특히,이 파일에 대한 쓰기 완료에 어떻게 응답합니까? 참고 : 이상적으로 “미완성”작문을 불필요하게 / (올바르게) 업로드하지 않도록 쓰기가 “완료”되었을 때 응답하고 싶습니다.
하드 링크의 수정을 잡으려면 CREATE
해당 링크를 따르고 추적 하는 inotify 이벤트에 대한 핸들러를 설정해야 합니다. 단순함 CREATE
은 비어 있지 않은 파일이 생성되었음을 의미 할 수도 있습니다. 그런 다음에 IN_MODIFY
/ IN_CLOSE_WRITE
어떤 파일에 대한 모든 링크 된 파일에뿐만 아니라이 같은 조치를 트리거 할 수 있습니다. 분명히 DELETE
이벤트 에서 해당 관계를 제거해야합니다 .
더 간단하고 강력한 접근 방식은 모든 파일을 주기적으로 해시하고 파일 내용이 변경되었는지 확인하는 것입니다.
보정
당좌 후 git
밀접하게 소스 코드를 실행 git
하여 strace
, 그 발견 git
사용 메모리 매핑 된 파일을 수행하지만, 대부분의 콘텐츠를 읽는. 사용법 xmmap
은 항상 호출 PROT_READ
만 참조하십시오 . . 따라서 아래의 이전 답변은 정답이 아닙니다 . 그럼에도 불구하고 정보 목적으로 여전히 여기에 보관하고 싶습니다.
-
당신은 볼 수 없습니다
IN_MODIFY
때문에 이벤트를packfile.c
사용하는mmap
파일 액세스가와inotify
에 대한 수정 사항을보고하지 않습니다mmap
에드 파일.로부터 inotify를 맨 :
inotify API는 mmap (2), msync (2) 및 munmap (2)로 인해 발생할 수있는 파일 액세스 및 수정을보고하지 않습니다.
답변
Git은 대부분 다음과 같이 수행되는 원자 파일 업데이트를 사용한다고 추측 할 수 있습니다 .
- 파일의 내용은 메모리로 읽히고 수정됩니다.
- 수정 된 내용은 별도의 파일 (일반적으로 원래 파일과 동일한 디렉토리에 있으며 무작위 (
mktemp
-스타일) 이름)로 작성됩니다. - 새 파일은
rename(2)
원래 파일 보다 d -d입니다. 이 작업을 통해 이름을 사용하여 파일을 열려고하는 모든 관찰자가 이전 내용이나 새 내용을 얻을 수 있습니다.
이러한 업데이트로 볼 수 있습니다 inotify(7)
와 같은 moved_to
디렉토리에있는 이벤트-이후 파일 “다시 나타납니다.”
답변
을 바탕으로 이 허용 대답 내가 사용되는 프로토콜을 기반으로 이벤트에 약간의 차이가있을 수 있습니다 가정 것 (즉, SSH 또는 https).
--no-hardlinks
옵션 을 사용하여 로컬 파일 시스템에서 복제를 모니터링 할 때 동일한 동작을 관찰 합니까?
$ git clone git@github.com:user/repo.git
# set up watcher for new dir
$ git clone --no-hardlinks repo new-repo
Linux 및 Mac 호스트 모두에서 실험을 실행하는 것으로 관찰 된 행동은 아마도 https://github.com/docker/for-mac/issues/896 의 원인이되는이 열린 문제를 제거 하지만 아마도 incase를 추가합니다.
답변
또 다른 가능성이 있습니다 (man inotify에서).
이벤트 큐가 오버 플로우 될 수 있습니다. 이 경우 이벤트가 손실됩니다. 강력한 응용 프로그램은 이벤트 손실 가능성을 정상적으로 처리해야합니다. 예를 들어, 응용 프로그램 캐시의 일부 또는 전부를 다시 작성해야 할 수도 있습니다. (단순하지만 비용이 많이 드는 방법 중 하나는 inotify 파일 디스크립터를 닫고 캐시를 비우고 새로운 inotify 파일 디스크립터를 작성한 다음 모니터 할 오브젝트의 시계 및 캐시 항목을 다시 작성하는 것입니다.)
그리고 git clone
많은 이벤트 흐름을 생성 할 수 있지만 이런 일이 발생할 수 있습니다.
이것을 피하는 방법 :
- 읽기 버퍼를 늘리고 fcntl (F_SETPIPE_SZ)을 시도하십시오 (이 접근 방식은 추측 한 적이 없습니다).
- 전용 스레드에서 큰 버퍼로 이벤트를 읽고 다른 스레드에서 이벤트를 처리하십시오.
답변
내가 몇 년 전에했던 실수를 나는 inotify를 두 번만 사용했습니다. 처음으로 내 코드는 간단하게 작동했습니다. 나중에 더 이상 해당 소스를 가지고 다시 시작하지 않았지만 이번에는 이벤트가 누락되어 이유를 알지 못했습니다.
이벤트를 읽을 때 실제로는 작은 이벤트를 읽는 것으로 나타났습니다. 나는 내가 생각한 것을 파싱했다. 그것이 전부라고 생각했다. 결국, 나는 수신 된 데이터에 더 많은 것이 있음을 발견했으며 단일 읽기에서 수신 된 모든 이벤트를 구문 분석하기 위해 작은 코드를 추가하면 더 이상 이벤트가 손실되지 않았습니다.