Linux 下文件监控
本文转自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中mask
| IN_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_MOVE | IN_MOVED_TO|IN_MOVED_FROM |
| IN_CLOSE | IN_CLOSE_WRITE|IN_CLOSE_NOWRITE |
| 不常用的flag | |
| IN_DONT_FOLLOW | 不follow符号链接 (since 2.6.15) |
| IN_EXCL_UNLINK | 当文件从监测目中unlink后,则不再报告该文件的相关event,比如监控/tmp使用 (since 2.6.36) |
| IN_MASK_ADD | 追打MASK到被监测的pathname |
| IN_ONESHOT | 只监测一次 |
| IN_ONLYDIR | 只监测目录 |
仅由read返回
| IN_IGNORED | inotify_rm_watch,文件被删除或者文件系统被umount |
| IN_ISDIR | 发生事件的是一个目录 |
| IN_Q_OVERFLOW | Event队列溢出 |
| IN_UNMOUNT | 文件系统unmount |
4. 例子
用途:监测指定文件或目录(或不指定则为当前目录)的一切动作。
使用:inotify [文件或目录]
#include <unistd.h>
#include <sys/inotify.h>
#include <stdio.h>
#include <error.h>
#include <errno.h>
#include <string.h>
#define ERROR(text) error(1, errno, "%s", text)
struct EventMask {
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];
}
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;
}
运行结果: vim 中 对监测目录中的 inotify.cc 进行保存
4913 IN_CREATE IN_OPEN IN_ATTRIB IN_CLOSE_WRITE IN_DELETE inotify.cc IN_MOVED_FROM inotify.cc~ IN_MOVED_TO inotify.cc IN_CREATE IN_OPEN IN_MODIFY IN_CLOSE_WRITE IN_ATTRIB inotify.cc~ IN_DELETE
可以看到,vim保存文件的流程为
创建一个4913文件用于检测vim对目录的控制权限
把inotify.cc更名为inotify.cc~
新建inotify.cc,并写入buffer
删除inotify.cc
Linux 下文件监控的更多相关文章
- Windows与Linux下文件操作监控的实现
一.需求分析: 随着渲染业务的不断进行,数据传输渐渐成为影响业务时间最大的因素.究其原因就是因为数据传输耗费较长的时间.于是,依托于渲染业务的网盘开发逐渐成为迫切需要解决的需求.该网盘的实现和当前市场 ...
- [转帖]Linux下inotify监控文件夹状态,发生变化后触发rsync同步
Linux下inotify监控文件夹状态,发生变化后触发rsync同步 https://www.cnblogs.com/fjping0606/p/6114123.html 1.安装工具--inotif ...
- Linux下文件的三种时间戳
Linux下文件的三种时间标记 三种时间对应关系表 column column column 访问时间 Access atime 修改时间 Modify mtime 状态改动时间 Change cti ...
- linux下文件结束符
linux下文件结束符,我试过了所有的linux,发现其文件的结束符都是以0a即LF结束的,这个是操作系统规定的,windows下是\r\n符结束,希望可以帮助大家. -------------转:来 ...
- dos2unix,去掉Linux下文件中的^M
Windows系统下使用VS2010编写好的CPP文件,想放到Linux上进行编译.发现Linux上文件中的每行代码末尾都跟着^M这个符号. 为什么同一份文件在windows上和Linux上显示的不一 ...
- linux下文件的复制、移动与删除
linux下文件的复制.移动与删除命令为:cp,mv,rm 一.文件复制命令cp 命令格式:cp [-adfilprsu] 源文件(source) 目标文件(destination) ...
- Linux下文件的权限
一.Linux下查看文件属性 命令为: [root@localhost ~]# ls -al 结果: ls是『list』的意思,重点在显示文件的文件名与相关属性.而选项『-al』则表示列出所有的文件详 ...
- LINUX下文件编译
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...
- linux 下文件误删恢复
linux 下文件误删恢复 0x01 事件背景 某天晚上写代码的时候,本来想删除当前目录下一个叫xxx的文件夹 rm -rdf ./xxx/*, 结果光顾着和人说话,一不留神手贱把命令敲成了rm -r ...
随机推荐
- 必须声明标量变量 "@列名"
这个主要是因为变量没有赋上值(见下图)
- C#获取磁盘列表与信息
方法1:使用Environment //获取当前计算机逻辑磁盘名称列表 String[] drives = Environment.GetLogicalDrives(); Console.WriteL ...
- 遍历页面上所有TextBox,并赋值为String.Empty
//不含母板页 foreach (System.Web.UI.Control txtobj in this.Page.Controls) { if (txtobj.GetType().Na ...
- java第一天的疑问
1字节 的 byte 2字节 的 char 精度 byte<short<char<int<long<float<double 随便打个整数默认为int 随便打个小数 ...
- ecshop模板如何修改详细图解
ecshop模板如何修改?很多人在问这个问题,今天就以图解的方式给大家详细说下.相信学完之后,你会很清楚如何修改ecshop模板,不管你是初学者还是程序高手. 1, ecshop的模板结构 ecsho ...
- 带格式导出数据到Excel
导出按钮事件 protected void Button1_Click(object sender, EventArgs e) { Response.Clear(); ...
- IE6浏览器兼容问题及部分解决方案(网上整理)
作为一个初涉前端技术的IT菜鸟,IE浏览器的兼容问题是一个不得不跨越的坎.为了能够在不同浏览器达到同样的显示效果,就不得不花心思想出办法实现兼容.由于各大主流浏览器内核不同,各自的实现标准有所差异,因 ...
- twsited(4)--不同模块用redis共享以及用web发送数据到tcpserver
上一章开头我们说,要连接之前flask系列文章中的用户,结果篇幅不够,没有实现. 今天我们把它实现一下.话说,不同模块之间,该如何联系在一起,通常都是mysql.redis.rabbitmq还有RPC ...
- 三分钟PJ隐藏SSID无线网络
一般来说用户可以通过路由或主机设置来隐藏无线信号的SSID网络信息,在这种情况下我们使用XP系统自带的无线信号扫描工具将看不到该无线网络的踪影,在这种情况下XP系统无线信号管理工具只能够看到将SSID ...
- Linux前传——第一次写技术博客
准备写技术博客了.不过,真的没什么技术,以后就写写学习上面遇到的问题与想法吧.