webtail——文件监控

文件监控直接通过了linux的inotify接口实现。这里没有考虑移植性,也就没像tailf那样,通过宏来判断是否支持inotify,如果不支持,降级使用循环轮寻的方式读取。

inotify的使用还是比较方便的基本上就是:inotify_init,inotify_add_watch,然后配合read系统调用,获取文件修改信息。因此实现也非常方便。

首先是在构造函数里面初始化inotify:
[cce lang=”cpp”]
inotifyFd = inotify_init();
[/cce]

然后提供一个watch接口,通过传入前文描述的TFile对象和内容读取的回调函数,添加对应文件的监控和回调。
[cce lang=”cpp”]
void FileWatcher::watch ( boost::shared_ptr< TFile > tFile, std::list< FileWatcher::ReadCallBack > callBackList )
{
if(!tFile->hasError() && !callBackList.empty()) {
int wd = inotify_add_watch(inotifyFd, tFile->name().c_str(), IN_MODIFY);
if(wd > 0) {
tFileMap.insert(std::make_pair<int, boost::shared_ptr<TFile> >(wd, tFile));
callBackMap.insert(std::make_pair<int, std::list<ReadCallBack> >(wd, callBackList));

//init read
std::string initContent = tFile->read();
BOOST_FOREACH(ReadCallBack &callback, callBackList) {
callback(initContent);
}
}
}
}
[/cce]
这里通过TFile的文件名,向内核注册添加该文件的modify事件,并且在注册成功之后,进行初始读取(这里有个小问题,由于后面websocket端没有做缓存,所以由于初始读取的时候还没有任何websocket客户端连接,所以通过web无法读取初始内容,也就是文件最后10行)。同时,这个类维护两个hashmap,分别是监听描述符wd->tFile和wd->callbacklist。

监听完成后,就是启动监听,也就是通过读取fd,感知被监听文件的变更,由于这里只监听了文件修改,那么读取到这个事件之后,就可以对该文件进行增量读取(前文已经描述了读取方法)。
[cce lang=”cpp”]
char * buffer = new char[inotifyBufferSize];
while(!_interrupted) {
if(read(inotifyFd, buffer, inotifyBufferSize) < 0) {
if(errno == EINTR) {
// interrupt
delete buffer;
return;
}
}
struct inotify_event *event = ( struct inotify_event * ) buffer;
int wd = event->wd;
BOOST_AUTO(tFileIter, tFileMap.find(wd));
if(tFileIter != tFileMap.end()) {
boost::shared_ptr<TFile> tFile = tFileIter->second;
std::string content = tFile->read();
BOOST_AUTO(iter, callBackMap.find(wd));
if(iter != callBackMap.end()) {
std::list<ReadCallBack> callbacks = iter->second;
BOOST_FOREACH(ReadCallBack &callback, callbacks) {
callback(content);
}
}
}
}
delete buffer;
[/cce]
这里参照inotify的文档,首先读取缓冲区大小设置为
[cce lang=”cpp”]
static const int inotifyBufferSize = sizeof(struct inotify_event) + NAME_MAX + 1;
[/cce]
也就是inotify_event结构的长度,和名字最大值。由于inotify_event是变长字段(包含一个可选的文件名字段),所以这里采用了系统限制的文件名最大值NAME_MAX,这个宏在climits中定义,在linux中大小为255字节。
然后通过系统调用read,读取文件描述符inotifyFd,这里如果没有新的事件产生,read会进入阻塞状态,节省系统资源。如果有返回,则处理返回的inotify_event对象(注意在监听modify事件的时候,是没有文件名的)。通过结构中的wd,从之前保存的hashmap中获取对应的tFile对象进行增量读取,然后再读取wd对应的回调函数,将读取内容返回。
这里有个小问题需要处理,就是如何中断读取。之前为了在gtest中能够通过单元测试的方式进行测试,通过查看手册可以知道,如果read调用被系统信号中断,会标记错误码为EINTR。所以,当读取失败的时候,可以通过对ERRNO检查,判断是否是信号中断。

由于程序会一直运行,知道通过信号终止,所以析构变的不是很重要了。这里析构函数里面通过调用inotify_rm_watch将之前保存的wd全部去掉,然后通过close调用交inotify的文件描述符关闭即可:
[cce lang=”cpp”]
FileWatcher::~FileWatcher()
{
if(inotifyFd > 0) {
boost::unordered::unordered_map<int, boost::shared_ptr<TFile> >::iterator iter;
for(iter = tFileMap.begin(); iter != tFileMap.end(); ++iter) {
inotify_rm_watch(inotifyFd, iter->first);
}

close(inotifyFd);
}
}
[/cce]

转载自:https://coolex.info/blog/406.html

时间: 2024-12-31 21:12:25

webtail——文件监控的相关文章

webtail 文件读取,文件监控,websocket

文件读取 先介绍下背景,之前遇到过服务器上需要长时间tail一个日志,之前经常是通过一个终端连到服务器上,但是对于长时间观察,就不太方便:老是要开着终端,没法用手机等移动设备查看:多人共享查看比较麻烦,都需要登录到服务器上. webtail实现类似于tail,能够持续读取一个文件,并将文件内容通过websocket,实时推送到web端.webtail文件读取基于linux的inotify,所以没有可移植性,websocket使用基于asio的websocketpp,代码维护在这里. webtai

使用文件监控对象FileSystemWatcher实现数据同步

原文 使用文件监控对象FileSystemWatcher实现数据同步 最近在项目中有这么个需求,就是得去实时获取某个在无规律改变的文本文件中的内 容.首先想到的是用程序定期去访问这个文件,因为对实时性要求很高,间隔不能超过1S,而且每次获取到文本内容都要去分发给WEB服务器做别的操作,而那 个文本的写入有时候会频繁,1秒可能多次,但是也有可能在相当长一段时间内是没有任何写入的.这样一来如果每秒都去访问文件的话,一个是IO问题,还有就是每次操作都会引起后端一系列程序的反应,文本在长时间内无写入的话

文件监控(教学版)

参考FileSpy写的文件监控程序,但比它的抽象多了.可能瑞星的文件驱动也是这样写的,否则它为什么老阻止我安装驱动呢.测试程序是一个命令行小程序,负责打开设备,开启监控和关闭监控,运行时开启和关闭两次.   在DebugView中查看输出信息,我只是想看看能不能达到目的,所以信息量很少.   在驱动程序中开启和关闭监控的代码:   VOID AttachedToDeviceByName (__in PWSTR DeviceName, __in BOOLEAN attach) {   UCHAR

在C#使用文件监控对象FileSystemWatcher 实现数据同步

       最近在项目中有这么个需求,就是得去实时获取某个在无规律改变的文本文件中的内容.首先想到的是用程序定期去访问这个文件,因为对实时性要求很高,间隔不能超过1S,而且每次获取到文本内容都要去分发给WEB服务器做别的操作,而那个文本的写入有时候会频繁,1秒可能多次,但是也有可能在相当长一段时间内是没有任何写入的. 这样一来如果每秒都去访问文件的话,一个是IO问题,还有就是每次操作都会引起后端一系列程序的反应,文本在长时间内无写入的话,一秒一次的触发一系列徒劳的事情太不可取了. 最终发现了c

第 5 章 lsof - list open files 文件监控

lsof - list open files 目录 5.1. $$ 5.2. 监控文件系统 5.3. 设备文件 5.4. 用户监控 5.5. 监控进程 5.6. 监控网络 5.7. lsof 高级用法 5.8. 根据文件描述列出对应的文件信息 Command.PID 和 User 列分别表示进程的名称 进程标识符 (PID) 和所有者名称. FD: 文件描述符,应用程序通过文件描述符识别该文件.如cwd txt等 (1) cwd : current working directory 应用程序的

JAVA轻量级文件监控

介绍     本文主要介绍一种轻量级的文件监控方式,对文件的Create & Change & Delete,都有一个对应的Event方法来进行处理.对于核心的File Monitor Class,我们继承一个监听适配器类FileAlterationListenerAdaptor,这样会更方便,就不用再去重写每个Event方法. File Generator Class package shuai.study.file.generator; import java.io.IOExcepti

java实现目录文件监控实例代码

Java 7之前的版本都是没有原生支持的,下面就说说JDK 1.7 以下版本平台的解决方案: 事件驱动方式,无需无目录扫描,但与平台相关 线程轮询扫描,纯java实现,完美跨平台,但监听文件较多时,扫描的量太大,响应不是非常及时,依赖于扫描间隔时间 JNotify属于事件驱动,所以不同的平台的处理方式不一样.所以需要在java.library.path里面添加jnotify.dll/jnotify_64bit.dll,最简单的解决方案直接修改代码.JNotify_win32.java的47和51

第 82 章 lsof - list open files 文件监控

Command.PID 和 User 列分别表示进程的名称 进程标识符 (PID) 和所有者名称. FD: 文件描述符,应用程序通过文件描述符识别该文件.如cwd txt等 (1) cwd : current working directory 应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改 (2) txt : program text (code and data) 该类型的文件是程序代码,如应用程序二进制文件本身或共享库,如上列表中显示的 /sbin/init

SQL server 2005部署FSA文件监控方案

安装完软件,我们先打开SQL server 2005,这是默认数据库 接着用Database Wizard建立数据库 点击Browse 选择要建立数据的数据库