dsoprea / PyInotify

An efficient and elegant inotify (Linux filesystem activity monitor) library for Python. Python 2 and 3 compatible.
GNU General Public License v2.0
242 stars 73 forks source link

Moves are not handled properly #97

Open rbiro-alarm opened 2 years ago

rbiro-alarm commented 2 years ago

PyInotify keeps track of watched files by path, but the kernel tracks them by inode and PyInotify doesn't update it's internal cache when a file is moved. Hence:

!/usr/bin/env python3

import inotify.adapters import os from threading import Thread import time from inotify.constants import IN_MOVED_FROM, IN_CLOSE_WRITE

i = inotify.adapters.Inotify()

os.system("mkdir foo") os.system("touch foo/bar") watch_file = i.add_watch("foo/bar", mask=IN_CLOSE_WRITE) watch_dir = i.add_watch("foo", IN_MOVED_FROM) print ("watch_dir = {}, watch_file={}".format(watch_dir, watch_file))

def mythread(): print ("in mythread") time.sleep(3) os.system("mv foo/bar foo/baz") os.system("touch foo/bar")

Thread(target=mythread, daemon=True).start()

for event in i.event_gen(yield_nones=False): (desc, type_names, path, filename) = event

print ("event: %s, %s, %s, %s" %(desc, type_names, path, filename))
if desc.wd == watch_dir:
    time.sleep(3)
    # "foo/bar" is now the new file.
    print ("adding watch again")
    watch_file2 = i.add_watch("foo/bar", mask=IN_CLOSE_WRITE)

Should watch foo/baz as well as foo/bar, but

./inotify_test.py mkdir: cannot create directory ‘foo’: File exists watch_dir = 2, watch_file=1 in mythread event: _INOTIFY_EVENT(wd=2, mask=64, cookie=2139762, len=16), ['IN_MOVED_FROM'], foo, bar adding watch again Path already being watched: [foo/bar]

A work around is to do a superficial remove of the old path to get it out of the cache without removing it from what is actually watched. However, if you do that, then you cannot later stop watching the original file.

crackwitz commented 2 years ago

I observe the same behavior. It's problematic.

This library (release on PyPI) fails to handle properly:

There is no active maintenance of this library. Single maintainer that lost interest, the fate of many potentially useful libraries.

I was hoping to simply use this library instead of my own, where I implemented all of that already, but didn't like the hackiness.

justbendev commented 1 year ago

@rbiro-alarm , @crackwitz This issue have been fixed in commit #34 but unfortunately the pip package have not been updated since 2018.

To fix this issue you can uninstall the package with

pip3 uninstall inotify

Then install it from github.

git clone https://github.com/dsoprea/PyInotify.git
cd PyInotify
python3 setup.py install

Have a great day 👋🏻