前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >文件监控-inotify安装与使用分享

文件监控-inotify安装与使用分享

原创
作者头像
恒恒
修改2020-04-24 17:02:16
5.1K0
修改2020-04-24 17:02:16
举报
文章被收录于专栏:恒恒的专栏

开篇:在Linux环境开发过程中,遇到需要监控某个目录的文件是否发生变化执行相应脚本,网上了解一下,inotify完美符合需求。

inotify-tools 是一个用C语言库,一个为Linux提供简单inotify接口的命令行程序。这些程序可以用于监视文件系统事件并执行相应操作,这些程序是用C语言来写的,除了需要Linux内核的inotify支持外,没有其他的依赖,使用方便。

inotify 在Linux内核 2.6.13 (June 18, 2005)版本中引入的一个新功能,它为用户态监视文件系统的变化提供了强大的支持,允许监控程序打开一个独立文件描述符,并针对事件集监控一个或者多个文件,例如打开、关闭、移动/重命名、删除、创建或者改变属性。

由于网上的资料都比较零散,在这里整理分享一下安装过程与使用例子。


一、安装:

首先查看系统内核是否支持inotify功能 ls -l /proc/sys/fs/inotify,出现如下内容说明支持:

代码语言:javascript
复制
total 0
-rw-r--r-- 1 root root 0 Apr 23 15:23 max_queued_events
-rw-r--r-- 1 root root 0 Apr 24 22:11 max_user_instances
-rw-r--r-- 1 root root 0 Apr 23 15:23 max_user_watches

或通过 uname -a 查看当前系统内核版本是否在2.6.13 以上:

代码语言:javascript
复制
Linux VM_3_105_centos 3.10.107 x86_64 GNU/Linux

1 、yun安装:

代码语言:shell
复制
rpm -qa inotify-tools #如果没安装
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
yum install inotify-tools -y

2、下载编译安装:

代码语言:shell
复制
下载地址:https://sourceforge.net/projects/inotify-tools/files
上传到你的linux服务器,执行解压,编译安装:
tar zxvf inotify-tools-3.13.tar.gz
cd inotify-tools-3.13
./configure  --prefix=/usr/local/inotify          
make && make install

二、inotify 的默认内核参数详解:

代码语言:javascript
复制
/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的上限,也就是每一个inotify实例可监控的最大目录数。如果监控的文件数目巨大,需要根据实际情况适当增加此值得大小。


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

三、inotify-tools 工具包中包含了两个命令:

inotifywait ======>>>>

代码语言:javascript
复制
inotifywait 仅执行阻塞,等待 inotify 事件,你可以使用它来监控任何一组文件和目录,或监控整个目录树(目录、子目录、子目录的子目录等等)
并且可以结合 shell 脚本,更好的使用 inotifywait。

命令格式:
inotifywait [-hcmrq] [-e <event> ] [-t <seconds> ] [--format <fmt> ] [--timefmt <fmt> ] <file> [ ... ]

选项参数:
-h|--help 显示帮助信息
@<file> 排除不需要监视的文件,可以是相对路径,也可以是绝对路径
--exclude <pattern> 正则匹配需要排除的文件,大小写敏感
--excludei <pattern> 正则匹配需要排除的文件,忽略大小写。
-m|--monitor 接收到一个事情而不退出,无限期地执行。默认行为是接收到一个事情后立即退出
-d|--daemon 跟--monitor一样,除了是在后台运行,需要指定--outfile把事情输出到一个文件。也意味着使用了--syslog
-r|--recursive 监视一个目录下的所有子目录
--fromfile <file> 从文件读取需要监视的文件或排除的文件,一个文件一行,排除的文件以@开头
-o|--outfile <file>   输出事件到文件
-s|--syslog 输出错误信息到系统日志
-q|--quiet 不输出详细信息,只输出事件
-qq 除了致命错误,不会输出任何信息
--timefmt <fmt> 指定时间格式,用于format选项中的%T格式
-c|--csv 输出csv格式
-t|--timeout <seconds> 设置超时时间,如果为0,则无限期地执行下去
-e|--event <event1> [ -e|--event <event2> ... ]  指定监听的时间,如果省略,则侦听所有事件
--format <fmt> 指定输出格式  
%w 表示发生事件的目录
%f 表示发生事件的文件
%e 表示发生的事件
%Xe 事件以“X”分隔
%T 使用由--timefmt定义的时间格式

可监听的事件:
access 文件或者目录被读
modify 文件或目录被写入
attrib 文件或者目录属性被更改
close_write 文件或目录关闭,在写模式下打开后
close_nowrite 文件或目录关闭,在只读模式打开后
close 文件或目录关闭,而不管是读/写模式
open 文件或目录被打开
moved_to 文件或者目录移动到监视目录
moved_from 文件或者目录移出监视目录
move 文件或目录移出或者移入目录
create 文件或目录被创建在监视目录
delete 文件或者目录被删除在监视目录
delete_self 文件或目录移除,之后不再监听此文件或目录
unmount 文件系统取消挂载,之后不再监听此文件系统

使用案例:

代码语言:shell
复制
监控当前目录,并且去掉vim产生的一些非预想的文件:

inotifywait -mr -e create -e delete -e modify --exclude "swp|4913|viminfo|~$" ./

出现如下表示已经开始监控:

Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.

在实际使用的过程中,可以使用-d --outfile 两个选项,在后台运行并且输出到某个文件,shell监控日志文件变更从而达到监控某目录下所有文件变更的目的。

inotifywatch======>>>>

代码语言:javascript
复制
inotifywatch 用来收集关于被监视的文件系统的统计数据,包括每个 inotify 事件发生多少次。

命令格式:
inotifywatch [-hvzrqf] [-e <event> ] [-t <seconds> ] [-a <event> ] [-d <event> ] <file> [ ... ]

由于inotifywatch只是用来做统计的,这里不扩展该命令的更多信息。

四、另一种的方法:

代码语言:javascript
复制
利用linux自身的inotify支持,编写C脚本来监听,代码如下:

#include <sys/inotify.h>  
#include <unistd.h>  
#include <string.h>  
#include <stdio.h>  
  
/* 
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  
}; 
 
*/  
  
int watch_inotify_events(int fd)  
{  
    char event_buf[512];  
    int ret;  
    int event_pos = 0;  
    int event_size = 0;  
    struct inotify_event *event;  
      
    /*读事件是否发生,没有发生就会阻塞*/  
    ret = read(fd, event_buf, sizeof(event_buf));  
      
    /*如果read的返回值,小于inotify_event大小出现错误*/  
    if(ret < (int)sizeof(struct inotify_event))  
    {  
        printf("counld not get event!\n");  
        return -1;  
    }  
      
    /*因为read的返回值存在一个或者多个inotify_event对象,需要一个一个取出来处理*/  
	while( ret >= (int)sizeof(struct inotify_event) )  
    {  
        event = (struct inotify_event*)(event_buf + event_pos);  
        if(event->len)  
        {  
            if(event->mask & IN_CREATE)  
            {  
                printf("create file: %s\n",event->name);  
            } 
	    else if ( event->mask & IN_MODIFY ){
                printf("modify file: %s\n",event->name);  		
	    }
        else  
        {  
			printf("delete file: %s\n",event->name);  
        }
      }
          
        /*event_size就是一个事件的真正大小*/  
        event_size = sizeof(struct inotify_event) + event->len;  
        ret -= event_size;  
        event_pos += event_size;  
    }      
    return 0;  
}  
  
int main(int argc, char** argv)  
{  
    int InotifyFd;  
    int ret;  
      
    if (argc != 2)  
    {  
        printf("Usage: %s <dir>\n", argv[0]);  
        return -1;  
    }  
      
    /*inotify初始化*/  
    InotifyFd = inotify_init();  
    if( InotifyFd == -1)  
    {  
        printf("inotify_init error!\n");  
        return -1;  
    }  
      
    /*添加watch对象*/  
    ret = inotify_add_watch(InotifyFd, argv[1], IN_CREATE |  IN_DELETE | IN_MODIFY);  
      
    /*处理事件*/  
    watch_inotify_events(InotifyFd);
  
    /*删除inotify的watch对象*/  
    if ( inotify_rm_watch(InotifyFd, ret) == -1)   
    {  
        printf("notify_rm_watch error!\n");  
        return -1;  
    }
      
    /*关闭inotify描述符*/  
    close(InotifyFd);        
    return 0;  
}

编译代码:
gcc inotify.c -o inotify  

在tmp目录下创建test目录:
mkdir /tmp/test  

检测/tmp/test目录,使用inotify机制:
./inotify /tmp/test &

在/tmp/test下创建1.txt文件:
test$ touch /tmp/test/1.txt

终端输出:
create file: 1.txt  

监控到文件变化inotify执行完成,可以通过shell脚本判断inotify是否运行中来判断目录文件是否有变更
ps aux | grep inotify |wc -l

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、安装:
  • 二、inotify 的默认内核参数详解:
  • 三、inotify-tools 工具包中包含了两个命令:
  • inotifywatch======>>>>
  • 四、另一种的方法:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档