웹사이트 검색

네트워크를 통한 Linux의 파일 변경 모니터링에 대한 생각


이 페이지에서

  1. 이게 왜?
  2. 가능한 시나리오:\n
  3. 참고:

잘 알려진 메커니즘인 inotify를 통해 Linux에서 디렉토리의 변경 사항을 모니터링할 수 있습니다. inotify를 사용하면 디렉토리에 대한 감시를 설정하고 내용에 대한 이벤트를 감시하도록 구성할 수 있으며 어떤 일이 발생할 때 파일 설명자에서 메시지를 받게 됩니다. 이것은 디렉토리가 하드 드라이브, SSD 또는 USB 드라이브와 같은 로컬 스토리지에 있을 때 완벽하게 작동하지만 스토리지가 다른 컴퓨터에 있을 때 디렉토리가 네트워크 파일 시스템에 있을 때는 충분하지 않습니다. 동일하거나 다른 파일 시스템을 통해 연결된 동일한 디렉터리에서 작업하는 다른 사용자는 파일을 제거할 수 있으며 파일에 설정한 감시는 알림을 받지 않습니다.

왜 이런거야?

의도적으로 inotify는 작업 결과(mkdir 또는 chmod와 같은)를 가져오지만 감시할 파일 시스템의 종류(블랙 박스)를 알 수 없습니다. 파일 시스템은 감시가 설정되었음을 "알지" 못하므로 원격 호스트에 누군가 디렉토리를 감시하기를 원한다고 알리는 것과 같은 올바른 조치를 취할 수 없습니다.

당신이 유일한 사용자라면 아무런 문제가 없습니다. 감시하려는 디렉터리에서 더 많은 사용자가 작업하면 문제가 됩니다.

이 동작을 공공 라이브러리와 비교할 수 있습니다. 당신이 유일한 사용자일 때, 당신이 어떤 책을 빌렸는지 알기 때문에 어떤 책이 이용 가능한지, 어떤 책이 없는지 알 수 있습니다. 당신이 유일한 사용자가 아니라 더 많은 사용자가 책을 빌릴 때 이것은 더 이상 불가능합니다.

이 경우 도서관의 누군가는 사용자가 빌린 것을 관리해야 하며(보통의 경우) 책이 있는지 여부를 알기 위해 이 사람에게 연락해야 합니다. 그것은 현재 존재하지 않는 책이 다시 구할 수 있을 때 누군가에게 알려달라고 요청하는 것과 같습니다.

이제 여러분에게 알리기 위해 라이브러리와 접촉하는 것은 Linux에서 작동하지 않습니다. 물론 라이브러리는 원격 스토리지이고 서버는 라이브러리에서 작업하는 "누군가"입니다.

Linux에서 이 작업을 수행하려면 감시가 설정되었음을 원격 서버에 알리는 것입니다.

실제로 CIFS 및 최신 버전의 NFS와 같은 파일 시스템에는 서버에 대한 감시 전송 지원이 포함되어 있습니다. 커널 4.1.2의 fs/cifs/cifssmb.c의 6438행에 있는 CIFS의 경우 이에 대한 SMB 메시지(NT_TRANSACT_NOTIFY_CHANGE)가 주석 처리됩니다. 그러나 여전히 존재합니다. 이것을 주석 처리한 이유는 오랫동안 Linux용 기본 fsnotify 시스템이 아닌 dnotify와 함께 작동했기 때문입니다.


네트워크 파일 시스템을 사용하여 Linux에서 시계 전달 작업을 수행하고 FUSE는 커널 공간을 통해 가능합니다.

최근 나는 FUSE를 사용하여 이 "시계를 서버로 전달"을 구현하려고 시도했습니다. 나는 패치해야했다 :

FUSE 커널 모듈은 fsnotify에서 알림을 받은 후 조치를 취합니다. 커널 모듈이 inodenumber 및 마스크와 함께 사용자 공간 데몬으로 보내는 새로운 작업 코드
FUSE_FSNOTIFY를 도입했습니다.

FUSE 라이브러리는 fs 이벤트를 수신 및 처리하고 VFS에 다시 보고합니다.

작동 방식을 자세히 살펴보면 백엔드의 사용자 공간 파일 시스템에서 시계가 성공적으로 설정되면(ENOSYS에 응답할 수도 있음) 백엔드는 언제라도 시계에서 이벤트를 보낼 수 있습니다. 시계가 제거되었습니다. 이 이벤트를 어떻게 해야 할까요?

가능한 시나리오:

추가 FUSE opcode FUSE_FSNOTIFY_EVENT를 도입하고 백엔드 프로토콜에서 수신한 이벤트의 마스크를 fsnotify가 이해하는 것으로 변환하고 새로운 opcode, watch의 inode, 항목 이름을 사용하여 FUSE 모듈로 다시 보냅니다. 번역된 마스크 그의 차례에 FUSE 모듈은 이벤트가 백엔드에 있다는 정보가 제공되는 리스너(inotify 및/또는 fanotify)에게 알리는 fsnotify 하위 시스템으로 보냅니다. (예를 들어 이벤트 마스크 IN_REMOTE를 inotify하려면 FAN_REMOTE를 fanotify하려면 추가 이벤트 플래그가 필요합니다). 이 정보로 무엇을 할지는 청취자에게 달려 있습니다. 로컬 VFS는 이미 최신 상태일 수도 있고 아닐 수도 있습니다.

메모:

백엔드의 마스크를 fsnotify가 이해하는 것으로 변환하는 것은 이벤트에 따라 매우 쉬울 수도 있고 쉽지 않을 수도 있습니다. 감시 디렉토리에서 항목 생성(또는 제거)과 같은 기본 이벤트는 간단하고(FS_CREATE 및 FS_DELETE resp.) 소유자 변경도 그리 어렵지 않지만(FS_ATTRIB) 확장 속성과 같은 것입니다(SMB 사용 많이)는 FS_ATTRIB와 같은 일반적인 것으로만 변환될 수 있습니다.

FUSE 모듈은 시계 및/또는 inode가 여전히 유효한지, 그리고 시계의 마스크가 이벤트 마스크에 적용되는지 확인해야 합니다.

추가 마스크 비트 IN_REMOTE(inotify용) 및 FAN_REMOTE(fanotify용)가 필요합니다.

이중 정보는 피해야 합니다. 이것은 까다 롭습니다. 예를 들어 감시가 켜져 있는 동일한 호스트의 감시된 디렉토리에 파일을 생성합니다. 이 작업이 성공하면 fsnotify 이벤트 FS_CREATE가 발생하고 FS_CREATE | FS_REMOTE 이벤트, 백엔드에서 작업이 성공적으로 수행되어 이 메시지가 표시됩니다(백엔드→퓨즈 라이브러리→FUSE 커널 모듈→fsnotify 하위 시스템→inotify 및/또는 fanotify).

이를 해결하는 한 가지 방법은 다른 사람이 시작한 이벤트만 전송하도록 백엔드에 요청하는 것입니다. 백엔드의 경우 FS 이벤트의 개시자(호스트)를 연결을 만드는 호스트와 비교하는 것은 매우 간단합니다.

또 다른 솔루션은 보고된 이벤트를 퓨즈 라이브러리 및 FUSE 모듈의 로컬 캐시와 비교하는 것입니다. 파일을 만드는 예제에서 라이브러리(및 FUSE 모듈)는 항목이 감시된 디렉터리에 이미 존재하는지 확인해야 합니다. 그렇지 않은 경우 이 호스트에서 시작하지 않은 것입니다. 삭제의 경우도 마찬가지입니다.

파일이 기록되거나 소유자가 변경되는 것과 같은 다른 이벤트의 경우 이 방법으로는 충분하지 않습니다. 원격에서 변경된 항목(예: 새 크기, 새 소유자)에 대한 추가 정보는 원격 호스트가 보내는 메시지에 있어야 합니다.

해당 정보가 백엔드에서 제공되지 않는 경우 다른 솔루션은 클라이언트를 대신하여 FS 이벤트 감시를 담당하는 데몬이 최근 로컬 이벤트의 캐시를 유지하도록 하는 것입니다. 원격 이벤트가 보고되고 캐시에서 로컬 동등 항목을 찾을 수 없으면 다른 호스트에서 시작됩니다. 특정 사용자에 대한 연결을 사용하여 이벤트가 보고되고 다른 사용자가 이벤트를 받을 수 있는 권한이 있거나 없을 수 있기 때문에 이것은 까다로울 수 있습니다. 그리고 이 캐시는 얼마나 클까요?

위에서 FUSE를 사용했는데 CIFS 및 NFS와 같은 다른 파일 시스템과 비슷하다고 생각합니다.

아 그리고 네, 또 다른 옵션이 있습니다. 5초마다 폴링하면 됩니다.

스테프 본