This article provides an introduction to Pyinotify’s features, how to install it, and examples of how to use it.

Review the previous article: Can you really use a search engine?

features

Pyinotify is a Python module that monitors file system changes. Pyinotify is based on a Linux kernel feature called inotify. Inotify is an event-driven notifier that exports system events from kernel to user mode through system calls. Pyinotify binds these system calls and provides a set of interface implementations on top of them that provide a generic and abstract way to operate on these functions.

The installation

Install the Pyinotify module using Python’s PIP tool.

$ pip install pyinotifyCopy the code

Quick start

Once you have Pyinotify installed, you can use the following examples to quickly monitor specific file or directory changes using Pyinotify. If you specify a directory, Pyinotify will listen for all files in that directory, but not subdirectories.

$ python -m pyinotify /tmpCopy the code

Let’s do something with the/TMP directory:

$ touch test_file
$ echo "echo test" > test_file
$ chmod u+x test_file
$ rm -f test_fileCopy the code

Pyinotify listens for events generated by commands while manipulating them:

-- 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>Copy the code

It’s worth noting that Pyinotify by default listens for all events generated by the system.

The default event field reads as follows:

The field names meaning
dir Whether the object generating the event is a directory
mask Pyinotify has predefined event values for each event
maskname Name of the event corresponding to the event value
name The name of the object that generated the event
path Pyinotify listens for events
pathname Generates the absolute path to the event object
wd The resource descriptor that the Linux Kernel inotify listens on

Pyinotify event list

The name of the event meaning
IN_ACCESS File accessed
IN_ATTRIB The file properties are changed
IN_CLOSE_NOWRITE Open and close the file in non-write mode
IN_CLOSE_WRITE Open and close the file in write mode
IN_CREATE A file or directory is created
IN_DELETE A file or directory is deleted
IN_DELETE_SELF The monitored file or directory is deleted (the monitored folder itself is deleted)
IN_DONT_FOLLOW‍

Not listening for symlinks (since kernel 2.6.15)

IN_IGNORED Inotify_rm_watch: the file is deleted or the file system is unmounted
IN_ISDIR The event is a directory
IN_MASK_ADD Update the MASK to the monitored pathnane
IN_MODIFY The file is modified.
IN_MOVE_SELF Monitored file or directory movement
IN_MOVED_FROM Files are moved out of monitored directories
IN_MOVED_TO Files are moved to the monitored directory
IN_ONLYDIR Only directories are monitored (since kernel 2.6.15)
IN_OPEN File opened
IN_Q_OVERFLOW Event Queue Overflow
IN_UNMOUNT The file system is unmounted

Use the sample

With an understanding of Pyinotify and the system events it supports, we can override Pyinotify’s event methods to output events in a specified format.

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()Copy the code

After running the sample code, let’s do the/TMP directory again:

$ touch test_file
$ echo "echo test" > test_file
$ chmod u+x test_file
$ rm -f test_fileCopy the code

Meanwhile, Pyinotify outputs the event as we expect:

-- 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_fileCopy the code

The above sample code listens for all events. If you want to listen for some events, modify the add_watch parameter section:

mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE
watcher.add_watch('/tmp', mask, auto_add=True, rec=True)Copy the code

You can add more event methods and monitor more system critical directories.

conclusion

There are many similar checking tools available under Unix/Linux, such as Tripwire, Afick, etc. Such a tool configuration is relatively simple to use, but it does not redefine events generated by the system, and event reports need to be output by mail. Pyinotify can be easily developed and used based on usage requirements. Its advantage is that it can be easily integrated into various systems, and the event data generated by the system can be slightly sorted and pushed to ELK, OpenFalcon and other platforms for visual display and alarm.

See the official use case for more features of Pyinotify:

https://github.com/seb-m/pyinotify/wiki/List-of-Examples