本篇文章介绍了Pyinotify的特性、如何安装及使用示例,方便入门学习。
回顾上篇文章:你真的会使用搜索引擎吗?
特性
Pyinotify 是一个监控文件系统变化的 Python 模块,Pyinotify 是基于一个叫 inotify 的 Linux 内核功能而开发的。inotify 是一个事件驱动通知程序,它的作用是通过系统调用将系统事件从内核态导出到用户态。Pyinotify 绑定了这些系统调用,并且在其上提供了一系列的接口实现,提供通用和抽象的方式来操作这些功能。
安装
使用 Python 的 pip 工具安装 Pyinotify 模块。
$ pip install pyinotify
Quick start
安装好 Pyinotify 后,你可以参考下面的例子来快速的使用 Pyinotify 监控指定文件或目录变化。如果你指定了一个目录,Pyinotify 将监听这个目录下的所有文件,但不会监听子目录。
$ python -m pyinotify /tmp
下面让我们对 / tmp 目录进行一些操作:
$ touch test_file
$ echo "echo test" > test_file
$ chmod u+x test_file
$ rm -f test_file
操作命令的同时 pyinotify 会监听到命令所产生的事件:
-- touch test_file --
<Event dir=False mask=0x100 maskname=IN_CREATE name=test_file path=/tmp pathname=/tmp/test_file wd=1>
<Event dir=False mask=0x20 maskname=IN_OPEN name=test_file path=/tmp pathname=/tmp/test_file wd=1>
<Event dir=False mask=0x4 maskname=IN_ATTRIB name=test_file path=/tmp pathname=/tmp/test_file wd=1>
<Event dir=False mask=0x8 maskname=IN_CLOSE_WRITE name=test_file path=/tmp pathname=/tmp/test_file wd=1>
-- echo "echo test" > test_file --
<Event dir=False mask=0x2 maskname=IN_MODIFY name=test_file path=/tmp pathname=/tmp/test_file wd=1>
<Event dir=False mask=0x20 maskname=IN_OPEN name=test_file path=/tmp pathname=/tmp/test_file wd=1>
<Event dir=False mask=0x2 maskname=IN_MODIFY name=test_file path=/tmp pathname=/tmp/test_file wd=1>
<Event dir=False mask=0x8 maskname=IN_CLOSE_WRITE name=test_file path=/tmp pathname=/tmp/test_file wd=1>
-- chmod u+x test_file --
<Event dir=False mask=0x4 maskname=IN_ATTRIB name=test_file path=/tmp pathname=/tmp/test_file wd=1>
-- rm -f test_file --
<Event dir=False mask=0x200 maskname=IN_DELETE name=test_file path=/tmp pathname=/tmp/test_file wd=1>
值得注意的是,Pyinotify 默认监听系统产生的所有事件。
默认事件字段解读如下:
| 字段名称 | 含义 |
|---|---|
| dir | 产生事件的对象是否为目录 |
| mask | Pyinotify 对每个事件预先定义好的事件值 |
| maskname | 事件值对应的事件名称 |
| name | 产生事件的对象名称 |
| path | Pyinotify 监听事件的项目 |
| pathname | 产生事件对象的绝对路径 |
| wd | Linux Kernel inotify 监听的资源描述符 |
Pyinotify 事件列表
| 事件名称 | 含义 |
|---|---|
| IN_ACCESS | 文件被访问 |
| IN_ATTRIB | 文件属性被更改 |
| IN_CLOSE_NOWRITE | 以非 write 方式打开文件并关闭 |
| IN_CLOSE_WRITE | 以 write 方式打开文件并关闭 |
| IN_CREATE | 文件或目录被创建 |
| IN_DELETE | 文件或目录被删除 |
| IN_DELETE_SELF | 被监测的文件或目录被删除(被监测的文件夹本身被删除) |
| IN_DONT_FOLLOW |
不监听符号链接 (since kernel 2.6.15) |
| IN_IGNORED | inotify_rm_watch,文件被删除或者文件系统被 umount |
| IN_ISDIR | 发生事件的是一个目录 |
| IN_MASK_ADD | 更新 MASK 到被监测的 pathnane 中 |
| IN_MODIFY | 文件被修改 |
| IN_MOVE_SELF | 被监测的文件或目录移动 |
| IN_MOVED_FROM | 文件移出被监测的目录 |
| IN_MOVED_TO | 文件移入被监测的目录 |
| IN_ONLYDIR | 只监测目录 (since kernel 2.6.15) |
| IN_OPEN | 文件被打开 |
| IN_Q_OVERFLOW | Event 队列溢出 |
| IN_UNMOUNT | 文件系统 unmount |
使用示例
了解 Pyinotify 以及它所支持的系统事件后,我们可以覆写 Pyinotify 的事件方法,将事件输出成指定的格式。
code:
# -*- coding: utf-8 -*-import pyinotifyclass MyEvent(pyinotify.ProcessEvent):def process_IN_ACCESS(self, e):print("ACCESS:", e.pathname)def process_IN_ATTRIB(self, e):print("CHANGE ATTR:", e.pathname)def process_IN_MODIFY(self, e):print("MODIFY:", e.pathname)def process_IN_CREATE(self, e):print("CREATE:", e.pathname)def process_IN_DELETE(self, e):print("DELETE:", e.pathname)def process_IN_OPEN(self, e):print("OPEN:", e.pathname)def process_IN_CLOSE_WRITE(self, e):print("CLOSE:", e.pathname)if __name__ == "__main__":
watcher = pyinotify.WatchManager()
watcher.add_watch('/tmp', pyinotify.ALL_EVENTS, auto_add=True, rec=True)
myEvent = MyEvent()
notifier = pyinotify.Notifier(watcher, myEvent)
notifier.loop()
运行示例代码后,下面让我们对 / tmp 目录再次进行操作:
$ touch test_file
$ echo "echo test" > test_file
$ chmod u+x test_file
$ rm -f test_file
同时 Pyinotify 按照我们预期的结果将事件进行输出:
-- touch test_file --
CREATE: /tmp/test_file
OPEN: /tmp/test_file
CHANGE ATTR: /tmp/test_file
CLOSE: /tmp/test_file
-- echo "echo test" > test_file --
MODIFY: /tmp/test_file
OPEN: /tmp/test_file
MODIFY: /tmp/test_file
CLOSE: /tmp/test_file
-- chmod u+x test_file --
CHANGE ATTR: /tmp/test_file
-- rm -f test_file --
DELETE: /tmp/test_file
以上的示例代码中监听了所有事件,若想监听部分事件请修改 add_watch 参数部分:
mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE
watcher.add_watch('/tmp', mask, auto_add=True, rec=True)
你可以增加更多的事件方法,监控更多的系统关键目录。
总结
目前 Unix/Linux 下有许多类似的检查工具,如 Tripwire、Afick 等。这样的工具配置使用起来相对简单,但是不能重新定义系统产生的事件,事件报告需要通过邮件输出。使用 Pyinotify 可以根据使用需求进行简单开发并使用。它的好处是可以很方便的集成到各个系统,系统产生的事件数据还可以稍作整理然后推送到 ELK、OpenFalcon 等平台进行可视化展示和告警。
Pyinotify 更多的功能请参考官方用例:
https://github.com/seb-m/pyinotify/wiki/List-of-Examples