使用pyinotify 监控多文件夹多目录是否有新文件生成内容是否变化

检测一个目录A是否有远程服务传过来的文件,有的话调用相关服务去解析或者处理此文件,处理完生成处理报告结果到另一个目录B,这就需要同时监控A、B两个目录是否有新文件生成,A生成了新文件就本地处理,B生成了新文件要发送出去。
找到了pyinotiy这个模块,Pyinotify是一个简单而有用的Python模块,用于在Linux中实时监控文件系统的更改 ,绑定三个系统调用,并支持其上的实现,提供了一个共同和抽象的手段来操纵这些功能。
作为系统管理员,您可以使用它来监视目标感兴趣的更改,如Web目录或应用程序数据存储目录及其他目录。

依赖关系
为了使用pyinotify ,您的系统必须运行:
Linux内核2.6.13或更高版本
Python 2.4或更高版本
如何在Linux中安装Pyinotify
首先检查系统上安装的内核和Python版本,如下所示:

# uname -r 
# python -V

一旦满足依赖关系,我们将使用pip来安装pynotify 。 在大多数Linux发行版中,如果您使用从python.org下载的Python 2> = 2.7.9或Python 3> = 3.4二进制文件, Pip已经安装,否则安装如下:

# yum install python-pip      [On CentOS based Distros]
# apt-get install python-pip  [On Debian based Distros]
# dnf install python-pip      [On Fedora 22+]

现在,像这样安装pyinotify:

# pip install pyinotify

它将从默认存储库安装可用版本,如果您希望具有最新的稳定版本的pyinotify ,请考虑将其克隆为git仓库,如下所示。

# git clone https://github.com/seb-m/pyinotify.git
# cd pyinotify/
# ls
# python setup.py install

脚本代码:

#!/usr/bin/python
# coding=UTF-8
import os
import pyinotify
import threading
from time import ctime,sleep

#监控文件目录是否有新文件传来,有的话提交给本地服务
class OnWriteHandler(pyinotify.ProcessEvent):
    def process_IN_CREATE(self, event): #函数名以"process_"开头,后面跟注册的监测类型
        #os.system('echo '+'create file:%s'%(os.path.join(event.path,event.name))) #之后用于nohup输出
        print "new file: %s " % os.path.join(event.path,event.name) #打印
        os.system('sampleserv submit ' + '%s'%(os.path.join(event.path, event.name))) #提交给文件处理服务,此处调用你自己的接口或者处理

def auto_compile(path='./samples'):
    wm = pyinotify.WatchManager()
    mask = pyinotify.IN_CREATE #监测类型,如果多种用|分开,pyinotify.IN_CREATE | pyinotify.IN_DELETE
    notifier = pyinotify.Notifier(wm, OnWriteHandler())
    wm.add_watch(path, mask,rec=True,auto_add=True)
    print '==> Start monitoring %s (type c^c to exit)' % path
    while True:
        try:
            notifier.process_events()
            if notifier.check_events():
                notifier.read_events()
        except KeyboardInterrupt:
            notifier.stop()
            break

#监控本地文件处理服务检测报告是否完成,完成的话发送
class OnAnalyzerHandler(pyinotify.ProcessEvent):
    def process_IN_CREATE(self, event):
        if event.name == 'report.json':
            print "new analyze reports: %s" % os.path.join(event.path, event.name)
            #调用接口发送报告,此处为调用你自己的接口或处理2

def wait_analyze(path='/home/analyses/'):
    wm = pyinotify.WatchManager()
    mask = pyinotify.IN_CREATE
    notifier = pyinotify.Notifier(wm, OnAnalyzerHandler())
    wm.add_watch(path, mask, rec=True, auto_add=True)
    print 'Start monitoring %s ' % path
    while True:
      try:
        notifier.process_events()
        if notifier.check_events():
          notifier.read_events()
      except KeyboardInterrupt:
        notifier.stop()
        break


threads = []
t1 = threading.Thread(target=auto_compile,args=('./samples',))
threads.append(t1)
t2 = threading.Thread(target=wait_analyze,args=('/home/prism/.cuckoo/storage/analyses/',))
threads.append(t2)

def threads_join(threads):
    '''
    令主线程阻塞,等待子线程执行完才继续,使用这个方法比使用join的好处是,可以ctrl+c kill掉进程
    '''
    for t in threads:
        while 1:
            if t.isAlive():
                sleep(10)
            else:
                break

if __name__ == "__main__":
    for t in threads:
            t.setDaemon(True)
            t.start()

    threads_join(threads)
    print "all over %s" %ctime()
    

运行两天之后发现个问题报错:no space left on device(抛出监控的nodes数量达到pyinotify 最大值了,没有剩余的可用),这时候就无法继续监控新文件的产生了。
可以通过几种方法解决。
一种是设置提高监控nodes的最大值:

sudo sysctl fs.inotify.max_user_watches=524288 
sudo sysctl -p 生效
查看目前的最大值 
To find your current limit, type this in your terminal: 
$cat /proc/sys/fs/inotify/max_user_watches
增加最大值 
Which is typically 8192 by default. 
To increase your limit, type this: 
$sudo sysctl fs.inotify.max_user_watches=16384 
永久设置最大值 
To permanently set this limit, type this:
$echo 16384 | sudo tee -a /proc/sys/fs/inotify/max_user_watches

第二种比较特殊,根据特殊情况做的特殊处理,监控数量达到最大值这种情况一般是由于目录下有新的子目录生成,如果没有子目录,本身目录下文件的数量达到一定数量后就会造成查看此目录的各种卡慢,所以产生纯文件的方案本来就不可取,要避免目录下只有文件且文件数量庞大。以此为据,只要你知道子目录产生的规律,就可以用一个链接每次更新链接到新的子目录,监控此链接指向的目录即可

while True:
        #判断latest软链接是否存在
        while os.path.islink(storage_path) == False:
            breport = True
            print "soft link is not exist!!!"
            sleep(5)
            continue

        #存在的话,读取链接目录
        realpath = os.readlink(storage_path)
        while True:
            filepath = ""
            try:
                filepath = os.readlink(storage_path)
            except:
                print "soft link is deleted"
                break

            if realpath != filepath:
        	    realpath = filepath
        	    print "soft link change,watch new dir"

第三种,老化文件,使监控目录中的文件数量保持在一定范围内,超过的要么删掉新加的,要么删掉超时的。
第四种,不用这个监控了,自己写~~~~

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用pyinotify中的WatchManager来监控多个路径,具体步骤如下: 1. 创建WatchManager对象并实例化一个Notifier对象。 ``` import pyinotify wm = pyinotify.WatchManager() notifier = pyinotify.Notifier(wm) ``` 2. 为每个要监控的路径创建一个ProcessEvent子类,并在类的process_IN_MODIFY方法中定义响应逻辑。 ``` class EventHandler(pyinotify.ProcessEvent): def __init__(self, path): self.path = path def process_IN_MODIFY(self, event): print("File modified:", event.pathname) ``` 3. 将每个路径和其对应的ProcessEvent子类实例添加到WatchManager中。 ``` paths = ['/path/to/dir1', '/path/to/dir2', '/path/to/dir3'] for path in paths: wm.add_watch(path, pyinotify.IN_MODIFY, rec=True, auto_add=True, event_class=EventHandler) ``` 其中,add_watch方法的参数说明如下: - path:要监控的路径。 - pyinotify.IN_MODIFY:要监控的事件类型(这里是文件修改事件)。 - rec=True:递归地监控目录。 - auto_add=True:自动添加创建的子目录。 - event_class=EventHandler:要使用的ProcessEvent子类。 4. 启动Notifier对象,开始监控。 ``` notifier.loop() ``` 完整代码示例: ``` import pyinotify class EventHandler(pyinotify.ProcessEvent): def __init__(self, path): self.path = path def process_IN_MODIFY(self, event): print("File modified:", event.pathname) wm = pyinotify.WatchManager() notifier = pyinotify.Notifier(wm) paths = ['/path/to/dir1', '/path/to/dir2', '/path/to/dir3'] for path in paths: wm.add_watch(path, pyinotify.IN_MODIFY, rec=True, auto_add=True, event_class=EventHandler(path)) notifier.loop() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值