inotify 心得

一、inotify简介

inotify是Linux内核2.6.13 (June 18, 2005)版本新增的一个子系统(API),它提供了一种监控文件系统(基于inode的)事件的机制,可以监控文件系统的变化如文件修改、新增、删除等,并可以将相应的事件通知给应用程序。该机制由著名的桌面搜索引擎项目beagle引入用于替代此前具有类似功能但存在诸多缺陷的dnotify。

inotify既可以监控文件,也可以监控目录。当监控目录时,它可以同时监控目录及目录中的各子目录及文件的。此外,inotify 使用文件描述符作为接口,因而可以使用通常的文件I/O操作select、poll和epoll来监视文件系统的变化。

inotify 可以监视的文件系统常见事件包括:
IN_ACCESS:文件被访问
IN_MODIFY:文件被修改
IN_ATTRIB,文件属性被修改
IN_CLOSE_WRITE,以可写方式打开的文件被关闭
IN_CLOSE_NOWRITE,以不可写方式打开的文件被关闭
IN_OPEN,文件被打开
IN_MOVED_FROM,文件被移出监控的目录
IN_MOVED_TO,文件被移入监控着的目录
IN_CREATE,在监控的目录中新建文件或子目录
IN_DELETE,文件或目录被删除
IN_DELETE_SELF,自删除,即一个可执行文件在执行时删除自己
IN_MOVE_SELF,自移动,即一个可执行文件在执行时移动自己

通过/proc接口中的如下参数设定inotify能够使用的内存大小:
1、/proc/sys/fs/inotify/max_queue_events
应用程序调用inotify时需要初始化inotify实例,并时会为其设定一个事件队列,此文件中的值则是用于设定此队列长度的上限;超出此上限的事件将会被丢弃;
2、/proc/sys/fs/inotify/max_user_instances
此文件中的数值用于设定每个用户ID(以ID标识的用户)可以创建的inotify实例数目的上限;
3、/proc/sys/fs/inotify/max_user_watches
此文件中的数值用于设定每个用户ID可以监控的文件或目录数目上限;

二、inotify-tools

inotify是一个API,需要通过开发应用程序进行调用,对于大多数用户来讲这有着许多不便,inotify-tools的出现弥补了这一不足。inotify-tools是一套组件,它包括一个C库和几个命令行工具,这些命令行工具可用于通过命令行或脚本对某文件系统的事件进行监控。它由Rohan McGovern开发,其项目网址为http://inotify-tools.sourceforge.net。

inotify-tools提供的两个命令行工具:
inotifywait:通过inotify API等待被监控文件上的相应事件并返回监控结果,默认情况下,正常的结果返回至标准输出,诊断类的信息则返回至标准错误输出。它可以在监控到对应监控对象上指定的事件后退出,也可以进行持续性的监控。
inotifywatch:通过inotify API收集被监控文件或目录的相关事件并输出统计信息。

inotifywait命令使用简介:
inotifywait尤其适用于在脚本中等待某事件的发生,并可基于特定的事件执行相应操作。如将其用于脚本中监控某指定目录中的文件上的修改、新建、删除、属性信息的改变,而后使用rsync命令将某事件对应的文件同步至其它主机上。其常用选项如下:
-m, --monitor:inotifywait的默认动作是在监控至指定文件的特定事件发生一次后就退出了,而使用此选项则可实现持续性的监控;
-r, --recursive:递归监控指定目录下的所有文件,包括新建的文件或子目录;如果要监控的目录中文件数量巨大,则通常需要修改/proc/sys/fs/inotify/max_users_watchs内核参数,因为其默认值为8192。
-e , --event :指定要监控的特定事件,默认是监控所有的事件;此处包括access, modify, attrib, close_write, close_nowirte, close, open, moved_to, moved_from, move, create, delete, delete_selt等;
--timefmt :当在--format选项中使用%T时,--timefrt选项则可以用来指定自定义的符合strftime规范的时间格式,此时间格式可用的格式符可以通过strftime的手册页获取;--timefrt后常用的参数是'%d/%m/%y %H:%M';
--format :自定义inotifywait的输出格式,如--format '%T %w %f';常用的格式符如下:
%w:显示被监控文件的文件名;
%f:如果发生某事件的对象是目录,则显示被监控目录的名字;默认显示为空串;
%T:使用--timefmt选项中自定义的时间格式;

例如,要监控/tmp/test目录及其内部所有文件上发生的create,delete,modify,close_write事件,则使用如下命令:
# inotify -r --timefmt '%d/%m/%y %H:%M' --format '%T %w %f' -e create,delete,modify,close_write /tmp/test

此命令在监控到某文件上第一次事件后就会退出,如果想一直监控,则需要为命令添加-m选项。

在很多场景中都会用到将某主机上的某目录下的所有文件改变实时同步至另一主机上的指定位置,这也可以通过在脚本中使用inotifywait结合rsync命令来实现,比如如下脚本:

#!/bin/bash

DESTHOST=172.16.100.6
DESTHOSTDIR=/www/htdocs/
SRCDIR=/www/htdocs/

inotifywait -mr --timefmt '%d/%m/%y %H:%M' --format '%T %w %f' \
-e create,delete,modify,attrib $SRCDIR | while read DATE TIME DIR FILE; do
$FILECHANGE=${DIR}${FILE}

rsync -avze 'ssh' $SRCDIR root@${DESTHOST}:${DESTHOSTDIR} &>/dev/null && \
echo "At ${TIME} on ${DATE}, file $FILECHANGE was backed up via rsync" >> /var/log/filesync.log

done

需要注意的是,此脚本中的rsync是通过ssh加密后进行文件传输的,因此需要事先配置好相应的ssh能够基于密钥对用户进行认证,以免每一次文件同步都需要用户手动输入密码。

当然,如果数据传输不需要加密,此处也可以通过在目录主机的启动rsyncd守护进程来实现。

三、配置rsyncd+inotify实现文件实时同步:

本案例实现监控原主机上指定目录中的所有文件变化,并将变化实时同步至目标主机的指定目录中;所用主机及相关目录如下:
源主机:RHEL5.4(x86),172.16.100.1, 文件所在的目录为/www/htdocs;
目标主机:RHEL5.4(x86),172.16.100.6, 文件所在的目录为/www/htdocs;

1、设定目标主机(本例为172.16.100.6)

本案例中采用基于rsync守护进程的方式进行数据同步,其数据传输过程是明文方式,因此只适用于在特定的场景中应用。

1)安装相关软件:
目标主机是接收别的主机发送来的文件的服务器,因此,其rsync需要以守护进程的方式工作。rsync服务通常基于超级守护进程xinetd管理的方式来实现,因此需要事先安装rysnc和xinetd:
# yum -y install rsync xinetd

2)为rsync提供配置文件/etc/rsyncd.conf,内容类似如下内容:
# Section 1: Global settings
uid = nobody
gid = nobody
use chroot = no
max connections = 3
strict modes = yes
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log
# Section 2:Directory to be synced
[htdocs]
path = /www/htdocs
ignore errors = yes
read only = no
write only = no
hosts allow = 172.16.0.0/16
hosts deny = *
list = false
uid = root
gid = root
auth users = wwwuser
secrets file = /etc/rsync.passwd

其中的相关指令及其说明可以通过rsyncd.conf的手册而获取。而其访问控制功能也可基于xinetd进行,具体方法请参照xinetd.conf的手册页。

3)提供secrets file所指定的口令文件/etc/rsync.passwd,其内容类似如下:
htdocsuser:passwOrdForhtdOcs

其中冒号前的是用户名,冒号后的是对应用户的密码。此文件不能为其他任意用户可访问,因此可用如下命令修改:
# chmod 600 /etc/rsync.passwd

4)配置服务可以开机启动:
# chkconfig rsync on
# chkconfig xinetd on
# service xinetd start

默认情况下,rsyncd监听的端口为873/TCP,这可以通过如下命令查看:
# netstat -tnlp | grep ":873"
tcp 0 0 0.0.0.0:873 0.0.0.0:* LISTEN 3653/xinetd

2、设定源主机

1)安装相关软件
源主机需要实时监控指定目录中的所有文件上与文件改变相关的事件,并在事件发生时将改变的数据同步至目录主机,因此,源主机上需要确保内核支持inotify,并安装inotify-tools和rsync。

rsync的安装参照目标主机的中的方式进行即可。

inotify-tools的安装可以基于源码编译的方式进行,也可以通过安装其rpm进行。
源码下载地址:http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz
rpm包下载页面:http://rpm.pbone.net/index.php3/stat/4/idpl/15265939/dir/redhat_el_5/com/inotify-tools-3.14-1.el5.i386.rpm.html

这里以编译源代码的方式演示安装过程:
# tar xf inotify-tools-3.14.tar.gz
# cd inotify-tools-3.14
# ./configure
# make
# make install
# echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
# ldconfig

2)为源主机的rsync提供通过htdocsuser用户同步文件至目标主机的口令文件
# echo 'passwOrdForhtdOcs' > /etc/rsync.passwd
# chmod 600 /etc/rsync.passwd

注意,对于RHEL5.4自带的2.6.8版本的rsync来说,其客户端(即此处的源主机上的rsync)的口令文件中只能保存用户的口令,而不能类似目标主机上可同时指定用户名。

3)建立脚本/root/bin/htdocsync.sh,通过inotifywait监控目标文件上的相应事件,并在事件触发时启动同步过程:
#!/bin/bash
#
DESTHOST=172.16.100.6
DESTHOSTDIR=/www/htdocs/
SRCDIR=/www/htdocs/

inotifywait -mr --timefmt '%d/%m/%y %H:%M' --format '%T %w %f' -e close_write,modify,delete,create,attrib $SRCDIR | while read DATE TIME DIR FILE; do

FILECHANGE=${DIR}${FILE}

rsync -avz --password-file=/etc/rsync.passwd $SRCDIR htdocsuser@${DESTHOST}::htdocs &>/dev/null && \
echo "At ${TIME} on ${DATE}, file $FILECHANGE was backed up via rsync" >> /var/log/websync.log
done

而后给此脚本执行权限,并执行即可:
# chmod u+x /root/bin/htdocsync.sh
# /root/bin/htdocsync.sh &

如果想让此功能可以在开机时自动启动,则可以通过如下方式进行:
# echo '/root/bin/htdocsync.sh &' >> /etc/rc.d/rc.local

inotify 心得的更多相关文章

  1. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  2. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

  3. 我的MYSQL学习心得(二) 数据类型宽度

    我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  4. 我的MYSQL学习心得(三) 查看字段长度

    我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  5. 我的MYSQL学习心得(四) 数据类型

    我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...

  6. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  7. 我的MYSQL学习心得(六) 函数

    我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  8. 我的MYSQL学习心得(七) 查询

    我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  9. 我的MYSQL学习心得(八) 插入 更新 删除

    我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...

随机推荐

  1. ImageMagick之PDF转换成图片(image)

    安装完ImageMagick之后,直接执行“magick convert f:\parseWord\tmp\testpdf.pdf f:\parseWord\tmp\testpdf.jpg”,会报错: ...

  2. 【SSM 2】spring常用注解

    声明:以下观点,纯依据个人目前的经验和理解,有不当之处,多指教! 一.基本概述 注解(Annotation):也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举 ...

  3. MessageFormat不支持{

    转自 :http://zqc-0101.iteye.com/blog/1140140 MessageFormat用来格式化一个消息,通常是一个字符串,比如: String str = "I' ...

  4. submit异步提交 回调的方法

    背景: mvc模式下,当submit表单的时候,后台Control自动绑定Model类,但是如果不用submit来提交,改用ajax提交的时候,后台Control无法获取前台form表单内相应Name ...

  5. jQuery Mobile 脚本加载问题

    刚开始使用jQuery Mobile,发现很多问题需要重新考虑,比如脚本加载问题. 在普通html中,如果a.html中有链接到b.html,b.html中有类似代码: $(document).rea ...

  6. VS2008的DLL项目添加了方法但是找不到怎么办?

      VS2008中建立了一个DLL项目,使用了一段时间后,在其中一个类中添加了一个方法,然后编译后,拷贝了新的.h文件到使用DLL的项目中,并且.dll和.lib也拷贝到了需要的位置,但是在目标项目中 ...

  7. oracle sql优化

    整理一下网上所看到sql优化方法 1.使用大写字母书写sql,因为oracle解释器会先将sql语句转换成大写后再解释 2    减少访问数据库的次数,多数情况下一条sql可以达到目的的,就不要使用多 ...

  8. 1-9 TCP/IP参考模型

    ISO/OSI参考模型与TCP/IP模型对比 一.网络访问层 功能:包括IP地址与物理硬件地址的映射以及将IP地址封装成帧. 基于不同类型的网络接口,网路访问层定义了和物理介质的连接 网路访问层包含了 ...

  9. 基于PHP生成静态页的实现方法

    t1.php 复制代码 代码如下: <?php// 方法一根据模版生成静态页面// replaceTemplateString函数用于替换模板中指定字符串function replaceTemp ...

  10. framebuffer应用编程实践

    framebuffer的使用主要包括4个部分: (1):首先需要打开设备文件 /dev/fb0. (2):获取设备的信息.包括可变信息和不可变信息,分别使用两个结构体来进行封装,这两个结构体在 < ...