使用 inotify 監視某資料夾的一舉一動
在 Linux 下監視某個資料夾的變化,有很多種方法,可以土法煉鋼的定時去掃描、檢查修改時間,也可以去將檔案一一開啟比對,不過往往這些過程,都伴隨著大量且多餘的 IO 存取。對此,使用 inotify 就顯得比較方便且有效率。自從 hal 的出現後,我們已經可以使用 inotify 去攔截某個檔案或資料夾一舉一動的 event,若是整合 GLib ,短短數行即可實作出來。
該範例將會監聽 /usr/share/applications 資料夾內的檔案更動 event ,並印出來。因為該資料夾是 FreeDesktop.org Spec 中用來記錄桌面 application 資訊的,當安裝或是刪除軟體時,即會收到檔案新增或刪除的 event。
#include <glib.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <errno.h>
void inotify_events_io_func(GIOChannel *channel, GIOCondition condition, gpointer data)
{
char buf[1024];
struct inotify_event *event;
gint index = 0;
gint len = 0;
gint fd = g_io_channel_unix_get_fd(channel);
while(((len = read(fd, &buf, sizeof(buf))) < 0) && (errno == EINTR));
while(index<len) {
event = (struct inotify_event*)(buf+index);
/* read events */
switch(event->mask)
{
case IN_MODIFY:
printf("MODIFY\n");
break;
case IN_CREATE
printf("CREATE\n");
break;
case IN_DELETE:
printf("DELETE\n");
break;
}
index += sizeof(struct inotify_event) + event->len;
}
}
int main(int argc, char* argv[])
{
GMainLoop *loop;
GIOChannel *channel;
gint ino_fd = 0;
gint ino_wd = 0;
/* inotify */
ino_fd = inotify_init();
ino_wd = inotify_add_watch(ino_fd, "/usr/share/applications", IN_MODIFY | IN_CREATE | IN_DELETE);
channel = g_io_channel_unix_new(ino_fd);
g_io_add_watch(channel, G_IO_IN, (GIOFunc)inotify_events_io_func, (gpointer)NULL);
loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
}
該範例將會監聽 /usr/share/applications 資料夾內的檔案更動 event ,並印出來。因為該資料夾是 FreeDesktop.org Spec 中用來記錄桌面 application 資訊的,當安裝或是刪除軟體時,即會收到檔案新增或刪除的 event。
但是只對當前的目錄,如何對二級目錄進行觀察?
回覆刪除我尚未研究過此課題,也許可將該目錄下之目錄一一列出,再監聽其 event。
回覆刪除純路過,
回覆刪除在下前陣子剛好也有在找file activity monitoring這方面的solution, 順便分享一下結果:
對於一次要能monitor整個filesystem上的activity, 這裡有一個名為fschange的kernel side solution:
http://stefan.buettcher.org/cs/fschange/index.html
網頁中提供的 'inotify->fschange Daemon' 實際上就是如Fred所提, 用列舉的方式去註冊所有的directories 的 inotify event, 來演譯fschange最後所要達到的成果