概述
inotity是内核达到2.6.13以上的Linux操作系统特性,用于监控文件系统操作,比如读取,写入和创建等。inotify用法简单灵活,比cron的繁忙轮询更加高效
inotify监控支持的文件操作
从inotify提供的Python API(anaconda4.8.3,Python3.7)源码来看,支持的文件操作如下所示
FLAG_COLLECTIONS = {'OP_FLAGS': {
'IN_ACCESS' : 0x00000001, # File was accessed,文件被访问
'IN_MODIFY' : 0x00000002, # File was modified,文件被修改
'IN_ATTRIB' : 0x00000004, # Metadata changed,文件元数据发生改变
'IN_CLOSE_WRITE' : 0x00000008, # Writable file was closed,可写文件关闭
'IN_CLOSE_NOWRITE' : 0x00000010, # Unwritable file closed,只读文件关闭
'IN_OPEN' : 0x00000020, # File was opened,文件被打开
'IN_MOVED_FROM' : 0x00000040, # File was moved from X,文件从X中被转移
'IN_MOVED_TO' : 0x00000080, # File was moved to Y,文件被移到Y
'IN_CREATE' : 0x00000100, # Subfile was created,文件被创建
'IN_DELETE' : 0x00000200, # Subfile was deleted,文件被删除
'IN_DELETE_SELF' : 0x00000400, # Self (watched item itself),不明白什么意思
# was deleted
'IN_MOVE_SELF' : 0x00000800, # Self (watched item itself) was moved
},
'EVENT_FLAGS': {
'IN_UNMOUNT' : 0x00002000, # Backing fs was unmounted
'IN_Q_OVERFLOW' : 0x00004000, # Event queued overflowed
'IN_IGNORED' : 0x00008000, # File was ignored
},
'SPECIAL_FLAGS': {
'IN_ONLYDIR' : 0x01000000, # only watch the path if it is a
# directory
'IN_DONT_FOLLOW' : 0x02000000, # don't follow a symlink
'IN_EXCL_UNLINK' : 0x04000000, # exclude events on unlinked objects
'IN_MASK_ADD' : 0x20000000, # add to the mask of an already
# existing watch
'IN_ISDIR' : 0x40000000, # event occurred against dir
'IN_ONESHOT' : 0x80000000, # only send event once
},
}
inotity的使用方法
基于Python实现的inotify文件监控功能需要用到pyinotify,使用方法大致可分为以下步骤
1、创建WatchManager对象,添加要监控的目录,以及文件事件
2、创建Notifier,并将WatchManager对象交给Notifier处理,这里结合了asyncio实现消息的异步io
# This is a inotify Python script.
# author:sword
# create_date:2020-08-26
import os
import pyinotify
import time
import asyncio
def write_log(content=""):
t = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
c = t+" "+content
with open("VSIlog.txt", "a") as f:
f.writelines(c.upper()+"\n")
f.close()
def watch_path_check(watch_path=""):
if not watch_path:
write_log("ERROR:WATCH_PATH MUST BE SET")
return False
else:
if not os.path.exists(watch_path):
write_log("ERROR:{} DOESN'T EXIST".format(watch_path))
return False
else:
write_log("INFO:WATCH_PATH {} IS FOUND,WATCHING...".format(watch_path))
return True
class OnIOHandler(pyinotify.ProcessEvent):
def process_default(self, event):
#do something new here
write_log("INFO:{} IS CREATED".format(str(event)))
def auto_compile(path="."):
if watch_path_check(path):
wm = pyinotify.WatchManager()
loop = asyncio.get_event_loop()
pyinotify.AsyncioNotifier(wm,loop)
wm.add_watch(path,pyinotify.ALL_EVENTS,rec=True,auto_add=True)
loop.run_forever()
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
WATCH_PATH="/home/sword/test"
auto_compile(WATCH_PATH)
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
启动程序,并且在/home/sword/test文件夹进行相关文件操作可以看到以下日志。
2020-08-30 20:05:18 INFO:WATCH_PATH /HOME/SWORD/TEST IS FOUND,WATCHING...
2020-08-30 20:05:22 INFO:<EVENT DIR=TRUE MASK=0X40000020 MASKNAME=IN_OPEN|IN_ISDIR NAME='' PATH=/HOME/SWORD/TEST PATHNAME=/HOME/SWORD/TEST WD=1 >
2020-08-30 20:05:22 INFO:<EVENT DIR=TRUE MASK=0X40000001 MASKNAME=IN_ACCESS|IN_ISDIR NAME='' PATH=/HOME/SWORD/TEST PATHNAME=/HOME/SWORD/TEST WD=1 >
2020-08-30 20:05:22 INFO:<EVENT DIR=TRUE MASK=0X40000010 MASKNAME=IN_CLOSE_NOWRITE|IN_ISDIR NAME='' PATH=/HOME/SWORD/TEST PATHNAME=/HOME/SWORD/TEST WD=1 >
2020-08-30 20:05:52 INFO:<EVENT DIR=FALSE MASK=0X100 MASKNAME=IN_CREATE NAME=CAT6.LOG PATH=/HOME/SWORD/TEST PATHNAME=/HOME/SWORD/TEST/CAT6.LOG WD=1 >
2020-08-30 20:05:52 INFO:<EVENT DIR=FALSE MASK=0X20 MASKNAME=IN_OPEN NAME=CAT6.LOG PATH=/HOME/SWORD/TEST PATHNAME=/HOME/SWORD/TEST/CAT6.LOG WD=1 >
2020-08-30 20:05:52 INFO:<EVENT DIR=FALSE MASK=0X4 MASKNAME=IN_ATTRIB NAME=CAT6.LOG PATH=/HOME/SWORD/TEST PATHNAME=/HOME/SWORD/TEST/CAT6.LOG WD=1 >
2020-08-30 20:05:52 INFO:<EVENT DIR=FALSE MASK=0X8 MASKNAME=IN_CLOSE_WRITE NAME=CAT6.LOG PATH=/HOME/SWORD/TEST PATHNAME=/HOME/SWORD/TEST/CAT6.LOG WD=1 >