基于Pyinotify打造系统完整性检测工具

3,182 阅读4分钟
原文链接: mp.weixin.qq.com

本篇文章介绍了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