使用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"

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

你可能感兴趣的:(python)