2013-12-17 123 views
0

我需要觀察一個包含多個子目錄的目錄,每個子目錄都有我需要監視的文件添加,修改和刪除的文件。遞歸地監視目錄以添加/修改/刪除文件

我找到了一些示例代碼,並且爲了使它工作而不得不稍微修改它,但它並不完全符合我的需要。它可以找到文件重命名,或在目錄(但不是子目錄)中刪除,但不響應文件修改。

我可以使用Google搜索找到的方法是單獨監視每個文件;但是,我有幾十萬個文件要監視,並且每個文件描述符都可能不明智。

在FreeBSD下有辦法做我需要做的事嗎?或者我將不得不尋找替代解決方案?

#include <sys/types.h> 
#include <sys/event.h> 
#include <sys/time.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(void) { 
    int f, kq, nev; 
    struct kevent change; 
    struct kevent event; 

    kq = kqueue(); 
    if (kq == -1) 
     perror("kqueue"); 

    f = open("/tmp/foo", O_RDONLY); 
    if (f == -1) 
     perror("open"); 

    EV_SET(&change, f, EVFILT_VNODE, 
      EV_ADD | EV_ENABLE | EV_ONESHOT, 
      NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 
      0, 0); 

    for (;;) { 
     nev = kevent(kq, &change, 1, &event, 1, NULL); 
     if (nev == -1) 
      perror("kevent"); 
     else if (nev > 0) { 
      if (event.fflags & NOTE_DELETE) { 
       printf("File deleted\n"); 
       break; 
      } 
      if (event.fflags & NOTE_EXTEND || 
       event.fflags & NOTE_WRITE) 
       printf("File modified\n"); 
      if (event.fflags & NOTE_ATTRIB) 
       printf("File attributes modified\n"); 
     } 
    } 

    close(kq); 
    close(f); 
    return EXIT_SUCCESS; 
} 

回答

1

正如你猜對了,kqueue是不可擴展的,因爲你有一個手柄抱到有問題的文件/目錄,即使在O_RDONLY模式。在Linux上,爲此目的使用inotifyhttp://linux.die.net/man/7/inotify),但我相信這個內核功能沒有FreeBSD端口!

如果您有時間和資源,您可以做的是查看BSD上audit的代碼(http://www.freebsd.org/cgi/man.cgi?query=audit&sektion=4),並嘗試爲BSD編寫inotify版本! O_O

+0

我不認爲使用inotify會更容易。 Inotify也不是遞歸的,你仍然可以獨立地監視每個文件。但審計框架是一個很好的建議。也許在這裏dtrace可能也很有用。 –

+0

您是否知道使用'audit'是否需要爲每個受監控文件打開'fd'。同樣在@KristofProvost,我不知道它不是遞歸的,如果需要遞歸解決方案,那很酷。主要的問題是保存所有這些文件描述符。 – OmnipotentEntity

+0

也聖誕快樂。 :D – OmnipotentEntity