1. Inotify 机制概述

1.1. Inotify 介绍

在日常的运维过程中,经常需要备份某些文件,或者对系统的某些文件进行监控,比如重要的配置文件等。如果需要作到实时同步或者监控,就需要使用内核的inotify机制
Inotify 是基于inode级别的文件系统监控技术,是一种强大的、细粒度的、异步的机制,它满足各种各样的文件监控需要,不仅限于安全和性能

  • Inotify 不需要对被监视的目标打开文件描述符,而且如果被监视目标在可移动介质上,那么在 umount 该介质上的文件系统后,被监视目标对应的 watch 将被自动删除,并且会产生一个 umount 事件。
  • Inotify 既可以监视文件,也可以监视目录。
  • Inotify 使用系统调用而非 SIGIO 来通知文件系统事件。
  • Inotify 使用文件描述符作为接口,因而可以使用通常的文件 I/O 操作select 和 poll 来监视文件系统的变化。

1.2. Inotify 可监视的文件系统事件

  • IN_ACCESS : 即文件被访问
  • IN_MODIFY : 文件被 write
  • IN_ATTRIB : 文件属性被修改,如 chmod、chown、touch 等
  • IN_CLOSE_WRITE : 可写文件被 close
  • IN_CLOSE_NOWRITE : 不可写文件被 close
  • IN_OPEN : 文件被open
  • IN_MOVED_FROM : 文件被移走,如 mv
  • IN_MOVED_TO : 文件被移来,如 mv、cp
  • IN_CREATE : 创建新文件
  • IN_DELETE : 文件被删除,如 rm
  • IN_DELETE_SELF : 自删除,即一个可执行文件在执行时删除自己
  • IN_MOVE_SELF : 自移动,即一个可执行文件在执行时移动自己
  • IN_UNMOUNT : 宿主文件系统被 umount
  • IN_CLOSE : 文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
  • IN_MOVE : 文件被移动,等同于(IN_MOVED_FROM | IN_MOVED_TO)

注:上面所说的文件也包括目录

1.3. Inotify内核版本支持

  • kernel 2.6.13开始,Inotify正式并入内核,RHEL5已经支持.
  • 看看是否有 /proc/sys/fs/inotify/目录,以确定内核是否支持inotify
      [root@RHEL5 Rsync]# ls -l /proc/sys/fs/inotify/total 0-rw-r--r-- 1 root root 0 Oct  9 09:36 max_queued_events-rw-r--r-- 1 root root 0 Oct  9 09:36 max_user_instances-rw-r--r-- 1 root root 0 Oct  9 09:36 max_user_watches
    

1.4. inotify 的默认内核参数

  • /proc/sys/fs/inotify/max_queued_events默认值: 16384 该文件中的值为调用inotify_init时分配给inotify instance中可排队的event的数目的最大值,超出这个值得事件被丢弃,但会触发IN_Q_OVERFLOW事件
  • /proc/sys/fs/inotify/max_user_instances默认值: 128 指定了每一个real user ID可创建的inotify instatnces的数量上限
  • /proc/sys/fs/inotify/max_user_watches默认值: 8192 指定了每个inotify instance相关联的watches的上限

注意: max_queued_events 是 Inotify 管理的队列的最大长度,文件系统变化越频繁,这个值就应该越大 
如果你在日志中看到Event Queue Overflow,说明max_queued_events太小需要调整参数后再次使用.

2. Inotify 在系统中使用

2.1. linux shell 下使用inotify

  • 下载安装 inotify-tools源码 rhel5/centos5 RPM包

    • inotifywait 仅执行阻塞,等待 inotify 事件。您可以监控任何一组文件和目录,或监控整个目录树(目录、子目录、子目录的子目录等等)
      在 shell 脚本中使用 inotifywait。
    • inotifywatch 收集关于被监视的文件系统的统计数据,包括每个 inotify 事件发生多少次。
  • shell脚本示例
      [root@localhost ]# cat /tmp/test.sh#!/bin/bashinotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format  '%T %w%f %e' --event modify,delete,create,attrib  /home/admin | while read  date time file eventdocase $event inMODIFY|CREATE|MOVE|MODIFY,ISDIR|CREATE,ISDIR|MODIFY,ISDIR)echo $event'-'$file;;MOVED_FROM|MOVED_FROM,ISDIR|DELETE|DELETE,ISDIR)echo $event'-'$file;;esacdone
    
  • 执行脚本,结果输出(这里测试删除了一个目录 rm -fr cronolog-1.6.2.bak)
      [root@localhost]# /tmp/test.sh DELETE-/home/admin/cronolog-1.6.2.bak/COPYINGDELETE-/home/admin/cronolog-1.6.2.bak/doc/cronolog.infoDELETE-/home/admin/cronolog-1.6.2.bak/doc/cronolog.texiDELETE-/home/admin/cronolog-1.6.2.bak/doc/Makefile.amDELETE-/home/admin/cronolog-1.6.2.bak/doc/Makefile.inDELETE-/home/admin/cronolog-1.6.2.bak/doc/texinfo.texDELETE-/home/admin/cronolog-1.6.2.bak/doc/cronosplit.1mDELETE-/home/admin/cronolog-1.6.2.bak/doc/MakefileDELETE-/home/admin/cronolog-1.6.2.bak/doc/cronolog.1mDELETE,ISDIR-/home/admin/cronolog-1.6.2.bak/docDELETE-/home/admin/cronolog-1.6.2.bak/TODODELETE-/home/admin/cronolog-1.6.2.bak/src/cronotest.cDELETE-/home/admin/cronolog-1.6.2.bak/src/cronolog.cDELETE-/home/admin/cronolog-1.6.2.bak/src/cronoutils.hDELETE-/home/admin/cronolog-1.6.2.bak/src/cronoutils.cDELETE-/home/admin/cronolog-1.6.2.bak/src/Makefile.amDELETE-/home/admin/cronolog-1.6.2.bak/src/Makefile.inDELETE-/home/admin/cronolog-1.6.2.bak/src/cronosplit.inDELETE-/home/admin/cronolog-1.6.2.bak/src/MakefileDELETE-/home/admin/cronolog-1.6.2.bak/src/cronosplitDELETE-/home/admin/cronolog-1.6.2.bak/src/config.hDELETE,ISDIR-/home/admin/cronolog-1.6.2.bak/srcDELETE-/home/admin/cronolog-1.6.2.bak/lib/getopt1.cDELETE-/home/admin/cronolog-1.6.2.bak/lib/getopt.hDELETE-/home/admin/cronolog-1.6.2.bak/lib/Makefile.amDELETE-/home/admin/cronolog-1.6.2.bak/lib/Makefile.inDELETE-/home/admin/cronolog-1.6.2.bak/lib/localtime_r.cDELETE-/home/admin/cronolog-1.6.2.bak/lib/getopt.cDELETE-/home/admin/cronolog-1.6.2.bak/lib/MakefileDELETE-/home/admin/cronolog-1.6.2.bak/lib/strptime.cDELETE,ISDIR-/home/admin/cronolog-1.6.2.bak/libDELETE-/home/admin/cronolog-1.6.2.bak/config.cacheDELETE-/home/admin/cronolog-1.6.2.bak/install-shDELETE-/home/admin/cronolog-1.6.2.bak/Makefile.amDELETE-/home/admin/cronolog-1.6.2.bak/READMEDELETE-/home/admin/cronolog-1.6.2.bak/AUTHORSDELETE-/home/admin/cronolog-1.6.2.bak/Makefile.inDELETE-/home/admin/cronolog-1.6.2.bak/testsuite/Makefile.amDELETE-/home/admin/cronolog-1.6.2.bak/testsuite/READMEDELETE-/home/admin/cronolog-1.6.2.bak/testsuite/Makefile.inDELETE-/home/admin/cronolog-1.6.2.bak/testsuite/MakefileDELETE,ISDIR-/home/admin/cronolog-1.6.2.bak/testsuiteDELETE-/home/admin/cronolog-1.6.2.bak/cronolog.specDELETE-/home/admin/cronolog-1.6.2.bak/NEWSDELETE-/home/admin/cronolog-1.6.2.bak/configureDELETE-/home/admin/cronolog-1.6.2.bak/ChangeLogDELETE-/home/admin/cronolog-1.6.2.bak/missingDELETE-/home/admin/cronolog-1.6.2.bak/config.logDELETE-/home/admin/cronolog-1.6.2.bak/aclocal.m4DELETE-/home/admin/cronolog-1.6.2.bak/MakefileDELETE-/home/admin/cronolog-1.6.2.bak/INSTALLDELETE-/home/admin/cronolog-1.6.2.bak/config.statusDELETE-/home/admin/cronolog-1.6.2.bak/configure.inDELETE-/home/admin/cronolog-1.6.2.bak/mkinstalldirsDELETE,ISDIR-/home/admin/cronolog-1.6.2.bak
    

    详细请参考 man inotify , man inotifywait

2.2. 使用incron实现重要配置文件监控

Incron是inotify的cron系统,与os本身的cron一样,包含一个后台守护进程(incrond)和一个事件编辑器(incrontab
与os本身的cron不同的仅仅是触发时间的是os对某个文件(夹)的操作而不是时间,由系统事件触发的机制,对于应用系统来说,几乎可以做到实时性。

  • 安装Incron Incron Rpm包

      [root@localhost]# yum install Incron
    
  • 查看 incron 支持的事件类型 incrontab -t ,编辑配置文件使用 incrontab -e
  • 配置文件格式说明(默认配置在/var/spool/incron/ 目录下)
      <path> <mask> <command>
    

    选项说明:
    <path>:欲监控的文件或者目录
    <mask>:os对监控对象发生的事件
    <command>:command可以是系统命令,也可以是脚本,不能是用系统的重定向,除非重定向写在脚本中。<Command>中还可以使用下面的这些变量:
    $@:代表<path>,即监控对象
    $#:发生系统事件的对象(例如监控了某个文件夹,其下的某个文件发生了变化,那么$#就代表了该文件名)
    $%:代表<mask>,即发生的事件

  • 配置举例:

    • /home/admin/a.txt IN_MODIFY echo "$@ $#" 表示文件abc一旦被修改,就执行 echo "$@ $#"
    • /home/admin/ IN_ALL_EVENTS echo "$@ $# $%" 表示目录下的文件任何事件触发,就执行 echo "$@ $#"
  • 启动incrond (/etc/init.d/incrond start),然后在 /home/admin目录删除 ssss 文件,查看日志 tail /var/log/cron ,有如下输出
      Mar 23 14:05:19 localhost incrond[6857]: (root) CMD (echo "/home/admin =  = IN_OPEN,IN_ISDIR")Mar 23 14:05:19 localhost incrond[6857]: (root) CMD (echo "/home/admin =  = IN_CLOSE_NOWRITE,IN_ISDIR")Mar 23 14:05:20 localhost incrond[6857]: (root) CMD (echo "/home/admin =  = IN_OPEN,IN_ISDIR")Mar 23 14:05:20 localhost incrond[6857]: (root) CMD (echo "/home/admin =  = IN_CLOSE_NOWRITE,IN_ISDIR")Mar 23 14:05:20 localhost incrond[6857]: (root) CMD (echo "/home/admin = ssss = IN_DELETE")
    

总体来说,在文件和目录实时监控还是很有效的,可以结合其他工具来作统一化的解决方案,比如使用syslog-ng作统一化收集,当然最重要还是要有场景.

2.3 linux API

使用inotify API有以下关键步骤:

使用inotify_init()创建一个inotify实例,返回的文件描述符用于后续操作中指代该实例。

使用inotify_add_watch向inotify实例的监控列表添加条目,即添加应用感兴趣的文件或目录。每个监控项包含一个路径名及相关的位掩码,位掩码指明所要监控的事件。inotify_add_watch将返回一个监控描述符,用于后续操作指代该监控项(inotify_rm_watch移除监控项)。

应用需要对inotify文件描述符执行read()操作以获取事件通知,read()调用会返回一个或多个inotify_event结构,记录了所发生的事件。

应用结束时关闭inotify描述符,这会自动清除与inotify实例相关的所有监控项。

  inotify可用于监控文件或目录。监控目录时,与路径自身及其所含文件相关的事件都会通知应用程序。

  inofity为非递归的,若想监控目录下整个目录树,需要对目录树下每个目录发起inotify_add_watch调用。

2.3.1、API

#include <sys/inotify.h>

int inotify_init(void);

int inotify_add_watch(int fd, const char *pathname, uint32_t mask);

int inotify_rm _watch(int fd, uint32_t wd);

2.3.2、inotify事件

  使用inotify_add_watch添加、修改监控项时,位掩码参数mask标识了针对 给定路径名要监控的事件。下表中“in”列列出了可以mask中定义的事件位。

2.3.3、读取inotify事件

  在监控列表中添加监控项后,应用程序可用read从inotify文件描述符中读取事件,以判定发生了哪些事件。若读取时还没有事件发生,read将阻塞直到事件发生(除非设置O_NONBLOCK标志)。

  事件发生后,每次调用read会返回一个缓冲区,包含一个或多个如下类型的结构:

struct inotify_event {int wd;  //Watch descriptor on which event occurreduint32_t mask;  //Bits describing event that occurreduint32_t cookie;  //Cookie for related events(for rename())uint32_t len;  //Size of 'name' fieldchar name[];  //Optional null-terminated filename
}

#include <sys/inotify.h>
#include <limits.h>
#include "tlpi_hdr.h"static void             /* Display information from inotify_event structure */
displayInotifyEvent(struct inotify_event *i)
{printf("    wd =%2d; ", i->wd);if (i->cookie > 0)printf("cookie =%4d; ", i->cookie);printf("mask = ");if (i->mask & IN_ACCESS)        printf("IN_ACCESS ");if (i->mask & IN_ATTRIB)        printf("IN_ATTRIB ");if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");if (i->mask & IN_CLOSE_WRITE)   printf("IN_CLOSE_WRITE ");if (i->mask & IN_CREATE)        printf("IN_CREATE ");if (i->mask & IN_DELETE)        printf("IN_DELETE ");if (i->mask & IN_DELETE_SELF)   printf("IN_DELETE_SELF ");if (i->mask & IN_IGNORED)       printf("IN_IGNORED ");if (i->mask & IN_ISDIR)         printf("IN_ISDIR ");if (i->mask & IN_MODIFY)        printf("IN_MODIFY ");if (i->mask & IN_MOVE_SELF)     printf("IN_MOVE_SELF ");if (i->mask & IN_MOVED_FROM)    printf("IN_MOVED_FROM ");if (i->mask & IN_MOVED_TO)      printf("IN_MOVED_TO ");if (i->mask & IN_OPEN)          printf("IN_OPEN ");if (i->mask & IN_Q_OVERFLOW)    printf("IN_Q_OVERFLOW ");if (i->mask & IN_UNMOUNT)       printf("IN_UNMOUNT ");printf("\n");if (i->len > 0)printf("        name = %s\n", i->name);
}#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))int
main(int argc, char *argv[])
{int inotifyFd, wd, j;char buf[BUF_LEN] __attribute__ ((aligned(8)));ssize_t numRead;char *p;struct inotify_event *event;if (argc < 2 || strcmp(argv[1], "--help") == 0)usageErr("%s pathname...\n", argv[0]);inotifyFd = inotify_init();                 /* Create inotify instance */if (inotifyFd == -1)errExit("inotify_init");/* For each command-line argument, add a watch for all events */for (j = 1; j < argc; j++) {wd = inotify_add_watch(inotifyFd, argv[j], IN_ALL_EVENTS);if (wd == -1)errExit("inotify_add_watch");printf("Watching %s using wd %d\n", argv[j], wd);}for (;;) {                                  /* Read events forever */numRead = read(inotifyFd, buf, BUF_LEN);if (numRead == 0)fatal("read() from inotify fd returned 0!");if (numRead == -1)errExit("read");printf("Read %ld bytes from inotify fd\n", (long) numRead);/* Process all of the events in buffer returned by read() */for (p = buf; p < buf + numRead; ) {event = (struct inotify_event *) p;displayInotifyEvent(event);p += sizeof(struct inotify_event) + event->len; //event->len 变动的文件名长度。}}exit(EXIT_SUCCESS);
}

linux inotify 监控文件系统事件相关推荐

  1. linux 高效的文件系统事件监控 内核级解析方案 inotify

    转载 http://www.lvtao.net/config/inotify.html linux 高效的文件系统事件监控 内核级解析方案 inotify 安装inotify-tools (http: ...

  2. Linux下监控文件系统

    Linux下监控文件系统 Linux的后台程序通常在机器没有问题的情况下,需要长期运行(比如说数个月,甚至是数年).但是,程序的配置文件有时候是需要定期作调整.为了不影响程序对外服务(不重启),动态加 ...

  3. Python Watchdog——监控文件系统事件

    文章目录 简介 安装 初试 重定向到日志中 Handler类型 命令行工具 动态日志监控 遇到的坑 参考文献 简介 Watchdog是一款用于监控文件系统事件的Python库,对不同平台的事件进行了封 ...

  4. inotify之文件系统事件监控使用入门

    inotify是linux文件系统事件监控机制,功能强大,控制简单,可以实现很多有用的功能.如:当一个文件被访问.打开.关闭.移动.删除等等时做一些处理.此功能需要内核支持,从kernel 2.6.1 ...

  5. linux流行开源监控框架,Inotify: 高效、实时的Linux文件系统事件监控框架

    概要 - 为什么需要监控文件系统? 在日常工作中,人们往往需要知道在某些文件(夹)上都有那些变化,比如: 通知配置文件的改变 跟踪某些关键的系统文件的变化 监控某个分区磁盘的整体使用情况 系统崩溃时进 ...

  6. inotify 实时的Linux文件系统事件监控

    标签:inotifywait 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://cqfish.blog.51cto.com/6222 ...

  7. Python Inotify 监视LINUX文件系统事件

    Inotify 可以监视的LINUX文件系统事件包括: --IN_ACCESS,即文件被访问  --IN_MODIFY,文件被write  --IN_ATTRIB,文件属性被修改,如chmod.cho ...

  8. linux下通过inotify-tools监控文件系统

    inotify-tools 是为linux下inotify文件监控工具提供的一套c的开发接口库函数, 同时还提供了一系列的命令行工具,这些工具可以用来监控文件系统的事件. inotify-tools是 ...

  9. linux --- inotify 文件系统变化通知机制

    Linux --- inotify 文件系统变化通知机制 在linux下开发过程中,用户态需要内核提供一些机制,以便用户态能够及时地得知内核或底层硬件设备发生了什么,从而能够更好地管理设备,给用户提供 ...

最新文章

  1. mybatis的资源过滤错误及xml文件编码错误
  2. 软件行业项目经理主要的职责是什么?(转)
  3. 优化C代码常用的几招
  4. 人人都是产品经理读书笔记(四)
  5. Linux 将文件打包、压缩并分割成指定大小
  6. 最短路径(弗洛伊德算法)
  7. CSS快速学习8:圆角切图、滚动条和图片整合技术
  8. onenote设置默认新建页面颜色非白色
  9. Python 凭什么打败 Java、C/C++,成为机器学习的唯一语言?
  10. 【附】Python安装
  11. android开发JNI之高级篇
  12. 5.4Irvine32库
  13. AIML相关内容学习整理
  14. 通过资源监视器排查网络高占用异常
  15. 软考中级网络工程师的就业前景以及考试要求
  16. maven--解决was cached in the local repository, resolution will not be reattempted until the update
  17. 蓝字冲销是什么意思_​红字发票和蓝色发票是什么意思
  18. 如何提高测试用例评审效率?
  19. mysql timediff函数极限值
  20. 面对职场“毕业”,PMPMO应该如何从容的应对?如何跳槽能够大幅度升职加薪?【大海午餐】

热门文章

  1. Nuxt3遇见的坑(四):图片动态渲染之后打包路径问题以及打包css样式问题
  2. 为什么前端都要学Vue?
  3. Swift - 单例
  4. QT调用D3D绘制旋转三角形
  5. hdu1852 Beijing 2008(约数之和 : 无逆元除法取模 | 等比数列分治求和)
  6. 约数之和【质因数分解+等比数列求和】
  7. 二本类 计算机类 大学录取分数线,重庆邮电大学二本专业,为什么录取分数线会超过一本线?...
  8. 计算机组成原理 - 存储器
  9. os.path.join (python路径拼接)
  10. python-mysql项目实战