So I setup some code to watch a config file for edits, which worked until I used VIM to edit the file, then I had to also watch the directory for renames and creations. Then I discovered that didn't catch renames higher in the path hierarchy. Then I looked into symlinks...gaaahhhh!
First setup a made up example showing one (of many) tricky symlink scenarios:
mkdir config1
touch config1/config
ln -s config1 machine1
mkdir config2
touch config2/config
ln -s config2 machine2
ln -s machine1 active
Now, given a filename like active/config that I want to watch, I can see how to get an inotify watch descriptor for:
config1/ -> watch active/ follow symlinks (watches inode for config1)
active/ -> watch active/ dont follow symlinks (watches inode for active symlink
active/config -> watch active/config (watches inode for config1/config)
How do I add a watch on the machine1 symlink? Do I need to find some way to manually walk each symlink adding watches for each along the way? How?
The purpose is to allow:
mkdir config3
touch config3/config
ln -s -f -n config3 machine1
And have inotify warn that active/config has been redirected. At the moment it looks like I'll have to add a watch for:
- target file inode
- every directory inode leading to the file (to detect moves/renames of directories)
- every symlink inode involved in reaching any of the above
There must be an easier way to just watch one file? Have I strayed from the path or is this really the way?
My answer is a straight "yes, you are doing it right".
After carefully reading the inotify syscall manpage, I cannot see any way of short of watching every step of a (possibly-symlinked) path-to-a-file in order to detect any and all changes to the full path.
This just seems to be the way inotify
works: it only looks at specific files or folders, and it does not do recursion on its own. That, plus having to explicitly follow symlinks, seems to match your 3-step plan to the letter.
Selected quotes from the manpage:
The following further bits can be specified in mask when calling inotify_add_watch(2): IN_DONT_FOLLOW (since Linux 2.6.15)
Don't dereference pathname if it is a symbolic link.
[...]
Limitations and caveats
Inotify monitoring of directories is not recursive: to monitor subdirectories under a directory, additional watches must be created. This can take a significant amount time for large directory trees. [...]
This FAQ also lends support for your strategy re symlinks:
Q: What about the IN_ONLYDIR and IN_DONT_FOLLOW flags? IN_ONLYDIR ensures that the event occur only on a directory. If you create such watch on a file it will not emit events. IN_DONT_FOLLOW forbids following symbolic links (these ones will be monitored themselves and not the files they point to).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With