Linux下使用inotify监控文件动作

来源:互联网 发布:淘宝彩票走势图 编辑:程序博客网 时间:2024/05/01 04:58

 原作者blog地址: http://www.jiangmiao.org/blog/2179.html

在日常应用中,常常会遇到以下场景,监控文件夹A,若文件夹中的B文件发生变化,则执行C命令。Linux下可以通过inotify完成该功能。
自从Linux kernel 2.6.13起,inotify以作为内核的一部份,同时需要glibc 2.4以上版本。

1. 相关函数

inotify_init() - 创建一个inotify实例
inotify_add_watch(int fd, const char *pathname, uint32_t mask) - 加入文件或目录到inotify进行监测
inotify_rm_watch(int fd, int wd) - 移除一个watcher

2. 相关结构

         struct inotify_event {               int      wd;       /* Watch descriptor */               uint32_t mask;     /* Mask of events */               uint32_t cookie;   /* Unique cookie associating related                                     events (for rename(2)) */               uint32_t len;      /* Size of name field */               char     name[];   /* Optional null-terminated name */           };

3. Mask

适用于 inotify_add_watch mask 与 read 返回的inotify_event中maskIN_ACCESS文件被访问IN_ATTRIB文件属性发生变化IN_CLOSE_WRITE以write方式打开文件并关闭IN_CLOSE_NOWRITE以非write方式打开文件并关闭IN_CREATE文件或目录被创建IN_DELETE文件或目录被删除(被监测的文件夹A中B文件被删除)IN_DELETE_SELF被监测的文件或目录被删除(被监测的文件夹A被删除)IN_MODIFY文件被修改IN_MOVE_SELF被监测的文件或目录移动IN_MOVED_FROM文件移出被监测的目录IN_MOVED_TO文件移入被监测的目录IN_OPEN文件被打开上述flag的集合IN_ALL_EVENTS以上所有flag的集合IN_MOVEIN_MOVED_TO|IN_MOVED_FROMIN_CLOSEIN_CLOSE_WRITE|IN_CLOSE_NOWRITE不常用的flagIN_DONT_FOLLOW不follow符号链接 (since 2.6.15)IN_EXCL_UNLINK当文件从监测目中unlink后,则不再报告该文件的相关event,比如监控/tmp使用 (since 2.6.36)IN_MASK_ADD追打MASK到被监测的pathnameIN_ONESHOT只监测一次IN_ONLYDIR只监测目录仅由read返回IN_IGNOREDinotify_rm_watch,文件被删除或者文件系统被umountIN_ISDIR发生事件的是一个目录IN_Q_OVERFLOWEvent队列溢出IN_UNMOUNT文件系统unmount

4. 例子


#include <unistd.h>  #include <sys/inotify.h>  #include <stdio.h>  #include <error.h>  #include <errno.h>  #include <string.h>  #include <iostream>using namespace std;#define ERROR(text) error(1, errno, "%s", text)    struct EventMask {      unsigned int flag;      const char *name;                };    int freadsome(void *dest, size_t remain, FILE *file)  {      char *offset = (char*)dest;      while (remain) {          int n = fread(offset, 1, remain, file);          if (n==0) {              return -1;          }      remain -= n;      offset += n;      }      return 0;  }    int main(int argc, char *argv[])  {      const char *target;      if (argc == 1) {          target = ".";      } else {          target = argv[1];      }          cout << "target:" << target;    EventMask event_masks[] = {          {IN_ACCESS, "IN_ACCESS"}        ,            {IN_ATTRIB, "IN_ATTRIB"}        ,            {IN_CLOSE_WRITE, "IN_CLOSE_WRITE"}   ,            {IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE"} ,            {IN_CREATE, "IN_CREATE"}        ,            {IN_DELETE, "IN_DELETE"}        ,            {IN_DELETE_SELF, "IN_DELETE_SELF"}   ,            {IN_MODIFY, "IN_MODIFY"}        ,            {IN_MOVE_SELF, "IN_MOVE_SELF"}     ,            {IN_MOVED_FROM, "IN_MOVED_FROM"}    ,            {IN_MOVED_TO, "IN_MOVED_TO"}      ,            {IN_OPEN, "IN_OPEN"}          ,            {IN_DONT_FOLLOW, "IN_DONT_FOLLOW"}   ,            {IN_EXCL_UNLINK, "IN_EXCL_UNLINK"}   ,            {IN_MASK_ADD, "IN_MASK_ADD"}      ,            {IN_ONESHOT, "IN_ONESHOT"}       ,            {IN_ONLYDIR, "IN_ONLYDIR"}       ,            {IN_IGNORED, "IN_IGNORED"}       ,            {IN_ISDIR, "IN_ISDIR"}         ,            {IN_Q_OVERFLOW, "IN_Q_OVERFLOW"}    ,            {IN_UNMOUNT, "IN_UNMOUNT"}       ,        };                        int monitor = inotify_init();      if ( -1 == monitor ) {          ERROR("monitor");      }        int watcher = inotify_add_watch(monitor, target, IN_ALL_EVENTS);      if ( -1 == watcher  ) {          ERROR("inotify_add_watch");      }       FILE *monitor_file = fdopen(monitor, "r");      char last_name[1024];      char name[1024];         /* event:inotify_event -> name:char[event.len] */      while (true) {      inotify_event event;      if ( -1 == freadsome(&event, sizeof(event), monitor_file) ) {          ERROR("freadsome");      }      if (event.len) {          freadsome(name, event.len, monitor_file);      } else {          sprintf(name, "FD: %d\n", event.wd);      }      if (strcmp(name, last_name) != 0) {          puts(name);          strcpy(last_name, name);      }    /* 显示event的mask的含义 */      for (int i=0; i<sizeof(event_masks)/sizeof(EventMask); ++i) {          if (event.mask & event_masks[i].flag) {            printf("\t%s\n", event_masks[i].name);          }      }      }       return 0;  }  


0 0