Linux가 파일 변경을 처리하는 방법을 배우고 있습니다.

라이브러리를 적용하는 것뿐만 아니라 기본 사항을 파악하는 것이 항상 중요하다고 생각합니다.

파일 변경 사항을 모니터링하는 방법은 무엇입니까?





소프트웨어 개발자로서 해당 분야에 익숙해지고 싶을 때 어떻게 하시나요? 맞습니다. 해당 사양을 찾습니다.

각 운영 체제에는 파일 변경에 반응하는 자체 메커니즘이 있습니다. 저는 Unix에서 일하기 때문에 오늘날 Unix가 어떻게 작동하는지 살펴보기만 했습니다. Windows , BSD 또는 macOS와 같은 다른 운영 체제에는 고유한 메커니즘이 있습니다.


Inotify - 파일 시스템 이벤트 모니터링



처음에는 dnotify가 있었지만 그게 역사입니다!

Wikipedia에서 인용:

inotify (inode notify) is a Linux kernel subsystem created by John McCutchan, which monitors changes to the filesystem, and reports those changes to applications. It can be used to automatically update directory views, reload configuration files, log changes, backup, synchronize, and upload.




Linux API 문서에서 메커니즘에 대해 이미 많은 것을 배울 수 있습니다.

다음은 짧은 인용문입니다.

The inotify API provides a mechanism for monitoring filesystem events. Inotify can be used to monitor individual files, or to monitor directories. When a directory is monitored, inotify will return events for the directory itself, and for files inside the directory.



Linuxsource code. 를 자세히 살펴볼 수도 있습니다.

이벤트 구성은 다음과 같습니다.

/*
 * struct inotify_event - structure read from the inotify device for each event
 *
 * When you are watching a directory, you will receive the filename for events
 * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
 */
struct inotify_event {
    __s32       wd;     /* watch descriptor */
    __u32       mask;       /* watch mask */
    __u32       cookie;     /* cookie to synchronize two events */
    __u32       len;        /* length (including nulls) of name */
    char        name[]; /* stub for possible name */
};



동작 모드와 데이터 구조를 자세히 살펴보면 모든 것이 어떻게 작동하는지 알 수 있습니다.


Go에서 구현



Go로 돌아가자. 물론 Go는 Linux API를 잘 다루고 있으며 여기에서 Inotify에 대한 기능도 찾을 수 있습니다.

Windows 의 경우에는 물론 비슷한 것이 있습니다.

Go 아래에는 예상대로 Linux, BSD 및 Windows를 포함하는 excellent library이 있습니다.

따라서 개별 구현에 대해 걱정할 필요가 없습니다.

그래서 우리는 그것을 모두 합쳤습니다.

먼저 새 감시자를 초기화해야 합니다.

go에서 평소와 같이 가능한 실수를 처리해야 합니다. 여기에서 패닉으로 오류에 반응합니다.

w, err := fsnotify.NewWatcher()
if err != nil {
   panic(err)
}

defer w.Close()


이제 모니터링할 디렉터리를 감시자에 추가합니다.

err = w.Add("/tmp")
if err != nil {
   panic(err)
}


그런 다음 실제 마법은 자체 이동 루틴에서 발생합니다.

go func() {
  for {
    select {
      case event, ok := <-w.Events:
        if !ok {
            return
        }

        if event.Has(fsnotify.Write) {
           fmt.Println("modified file:", event.Name)
        }

      case err, ok := <-watcher.Errors:
        if !ok {
            return
        }
        fmt.Println("error:", err)
      }
    }
  }()

go func() {}()를 사용하여 기본 스레드와 "병렬"로 실행되는 고유한 go 루틴을 시작합니다.

Go 루틴은 훌륭하고 완전히 사랑합니다.

기본 문이 없기 때문에 select는 이벤트가 발생할 때까지 실행을 차단합니다.

이제 운영 체제가 /tmp 디렉토리에 대한 변경 사항을 보고하면 이를 알리고 이에 대응할 수 있습니다.


그게 다야.

좋은 웹페이지 즐겨찾기