在linux下使用inotify监控,能不能够知道监控目录下子目录中是哪个文件被修改了。。。求方法。。。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在linux下使用inotify监控,能不能够知道监控目录下子目录中是哪个文件被修改了。。。求方法。。。相关的知识,希望对你有一定的参考价值。
现在只能通过event->mask & IN_ISDIR 知道子目录被修改了,具体里面哪个文件就没法得知了
这个我们期末考试考过。inotify只能监控单层目录变化,不能监控子目录中的变化情况。
如果需要监控子目录,需要在调用inotify_add_watch(int fd, char *dir, int mask):int建立监控时,递归建立子目录的监控,伪代码如下
void addwatch(int fd, char *dir, int mask)
wd = inotify_add_watch(fd, dir, mask);
向目录集合加入(wd, dir);
for (dir下所有的子目录subdir)
addwatch(fd, subdir, mask);
这样就可以得到一个目录集合,其中每一个wd对应一个子目录。
当你调用read获取信息时,可以得到一个下面的结构体
struct inotify_event
int wd; /* Watch descriptor. */
uint32_t mask; /* Watch mask. */
uint32_t cookie; /* Cookie to synchronize two events. */
uint32_t len; /* Length (including NULs) of name. */
char name __flexarr; /* Name. */
;
其中,通过event->wd和刚才记录的目录集合可以知道变动的具体子目录。
event->name为具体的文件名称。
event->name是一个char name[0]形式的桩指针,具体的name占据的长度可以由event->len得出
我的监控部分代码如下:
enum EVENT_SIZE = sizeof(struct inotify_event);
enum BUF_SIZE = (EVENT_SIZE + 16) << 10;
void watch_mon(int fd)
int i, length;
void *buf;
struct inotify_event *event;
buf = malloc(BUF_SIZE);
while ((length = read(fd, buf, BUF_SIZE)) >= 0)
i = 0;
while (i < length)
event = buf + i;
if (event->len)
具体处理函数(event);
i += EVENT_SIZE + event->len;
close(fd);
exit(1);
在你的具体处理函数中,通过wd辨识子目录,通过name辨识文件
这是利用C++STLmap写的一个范例,可以监视当前目录下(含子目录)的变化,创建,删除过程(新建立的目录不能监视,只能通过监视到创建新目录的事件后重新初始化监视表)
新版1.1.0,可以监视创建的子目录,方法是,当do_action探测到新目录创建的动作时,调用inotify_add_watch追加新的监视
/*
Copyright (C) 2010-2011 LIU An (SuperHacker@china.com.cn)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <errno.h>
#include <dirent.h>
#include <map>
#include <string>
using namespace std;
void addwatch(int, char*, int);
static int filter_action(uint32_t mask);
int watch_init(int mask, char *root);
void addwatch(int fd, char *dir, int mask);
static void do_action(int fd, struct inotify_event *event);
void watch_mon(int fd);
static void send_mess(char *name, char *act, int ewd);
void append_dir(int fd, struct inotify_event *event, int mask);
map<int, string> dirset;
enumMASK = IN_MODIFY | IN_CREATE | IN_DELETE;
int main(int argc, char **argv)
int fd;
if (argc != 2)
fprintf(stderr, "Usage: %s dir\n", argv[0]);
exit(1);
fd = watch_init(MASK, argv[1]);
watch_mon(fd);
return 0;
int watch_init(int mask, char *root)
int i, fd;
if ((fd = inotify_init()) < 0)
perror("inotify_init");
addwatch(fd, root, mask);
return fd;
void addwatch(int fd, char *dir, int mask)
int wd;
char subdir[512];
DIR *odir;
struct dirent *dent;
if ((odir = opendir(dir)) == NULL)
perror("fail to open root dir");
exit(1);
wd = inotify_add_watch(fd, dir, mask);
dirset.insert(make_pair(wd, string(dir)));
errno = 0;
while ((dent = readdir(odir)) != NULL)
if (strcmp(dent->d_name, ".") == 0
|| strcmp(dent->d_name, "..") == 0)
continue;
if (dent->d_type == DT_DIR)
sprintf(subdir, "%s/%s", dir, dent->d_name);
addwatch(fd, subdir, mask);
if (errno != 0)
perror("fail to read dir");
exit(1);
closedir (odir);
enum EVENT_SIZE = sizeof(struct inotify_event);
enum BUF_SIZE = (EVENT_SIZE + 16) << 10;
void watch_mon(int fd)
int i, length;
void *buf;
struct inotify_event *event;
buf = malloc(BUF_SIZE);
while ((length = read(fd, buf, BUF_SIZE)) >= 0)
i = 0;
while (i < length)
event = (struct inotify_event*)(buf + i);
if (event->len)
do_action(fd, event);
i += EVENT_SIZE + event->len;
close(fd);
exit(1);
static char action[][10] =
"modified",
"accessed",
"created",
"removed"
;
enumNEWDIR = IN_CREATE | IN_ISDIR;
static void do_action(int fd, struct inotify_event *event)
int ia, i;
if ((ia = filter_action(event->mask)) < 0)
return;
if ((event->mask & NEWDIR) == NEWDIR)
append_dir(fd, event, MASK);
send_mess(event->name, action[ia], event->wd);
void append_dir(int fd, struct inotify_event *event, int mask)
char ndir[512];
int wd;
sprintf(ndir, "%s/%s", dirset.find(event->wd)->second.c_str(),
event->name);
wd = inotify_add_watch(fd, ndir, mask);
dirset.insert(make_pair(wd, string(ndir)));
static int filter_action(uint32_t mask)
if (mask & IN_MODIFY)
return 0;
if (mask & IN_ACCESS)
return 1;
if (mask & IN_CREATE)
return 2;
if (mask & IN_DELETE)
return 3;
return -1;
static void send_mess(char *name, char *act, int ewd)
char format[] = "%s was %s.\n";
char file[512];
sprintf(file, "%s/%s", dirset.find(ewd)->second.c_str(), name);
printf(format, file, act);
参考资料是我们作业的提交,没有考虑递归创建子目录监控的问题。
参考资料:http://59.67.33.217/homeworkref/sources/2010-2011-1.2008.software.os.inotify.tar.xz
参考技术A 你可以试试自己用 mingw 编译一个 DOS 下面可用的 tail 啊~如果你用 windows 的 cmd 。可以看看 powershell 有没有这个命令。
或者尝试安装一个 cygwin ,里面我记得有这个命令。之后用 cywin 的 bash 命令行当命令行用。
你要是用纯 DOS ,貌似你可以放弃计算机了……
NFS+inotify实时同步
Inotify简介
Inotify是一种文件系统事件通告机制,能够实时监控文件系统下文件的访问、修改、删除等各种变化情况并将其作为事件通告给用户态应用程序。Linux内核从2.6.13版本后已经集成了Inotify的功能,用户只需安装inotify应用程序即可实现对文件系统的监控。
配置Rsync服务端
rpm -qa | grep rsync vim /etc/rsyncd.conf uid = rsync #客户端进行数据传输时所使用的用户 gid = rsync #客户端进行数据传输时所使用的用户组 user chroot = no #安全相关 max connections = 200 #最大连接数 timeout = 300 #超时时间,客户端连接后300s不传输自动断开 pid file = /var/run/rsyncd.pid #进程号文件 lock file = /var/run/rsync.lock #锁文件 log file = /var/log/rsyncd.log #日志文件 ignore errors #忽略错误 read only = false #可写 list = false #客户端不能ls等进行列表 hosts allow = 172.16.1.0/24 #允许连接的主机 #hosts deny = 0.0.0.0/32 #拒绝的主机 auth users = rsync_backup #客户端登录账号名 secrets file = /etc/rsync.password #密码文件,用于验证 [backup] #模块名称 path = /backup/ #提供访问的目录 [nfsbackup] path = /nfsbackup useradd rsync -s /sbin/nologin –M mkdir /backup chown rsync.rsync /backup vim /etc/rsync.password rsync_backup:peterwang chmod 600 /etc/rsync.password rsync --daemon ps -ef | grep rsync | grep -v grep lsof -i :873 echo "/usr/bin/rsync --daemon" >> /etc/rc.local
配置NFS服务端
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo yum install -y inotify-tools vim /etc/rsync.password peterwang chmod 600 /etc/rsync.password mkdir /server/scripts -p cd /server/scripts vim inotify.sh #!/bin/bash export PATH=/bin:/usr/bin:/usr/local/bin SRC=/data DEST=nfsbackup IP=172.16.1.41 USER=rsync_backup PASSFILE=/etc/rsync.password inotifywait -mrq --format ‘%w%f‘ -e modify,create,move,delete,attrib $SRC | while read line do NUM=$(echo $line | grep -o "/" | wc -l) if [ $NUM -gt 2 ];then DIR=$(echo $line | awk -F "/" ‘{print "/"$2"/"$3}‘) rsync -az $DIR --delete rsync://[email protected]$IP/$DEST --password-file=$PASSFILE else rsync -az $SRC/ --delete rsync://[email protected]$IP/$DEST --password-file=$PASSFILE fi done & sh inotify.sh echo "/bin/sh /server/scripts/inotify.sh " >> /etc/rc.local
以上是关于在linux下使用inotify监控,能不能够知道监控目录下子目录中是哪个文件被修改了。。。求方法。。。的主要内容,如果未能解决你的问题,请参考以下文章
Haskell:在不轮询的情况下监控文件(在 linux 中使用 inotify)