inotify_add_watch(2)
Watch a file or directory for filesystem events and read them off a file descriptor.
- Since
- Linux 2.6.13check your kernel →
- glibc
- glibc 2.4
- System
- Linux
- Man page
- inotify_add_watch(2)
Synopsis
#include <sys/inotify.h>
int inotify_init1(int flags);
int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
int inotify_rm_watch(int fd, int wd);Rod's take
inotify is the right answer for anything that was polling a file on a timer. Three syscalls and you have an fd that delivers events into epoll. The traps: watch IN_CLOSE_WRITE not IN_MODIFY (atomic-write tools rename, not modify-in-place), always check IN_Q_OVERFLOW or you miss events silently when under load, and max_user_watches defaults to 65536 which sounds like a lot until you watch a source tree. The name field is only populated on directory watches; for a single-file watch, ev->len is zero.
Flags and arguments that matter
| Name | What it does |
|---|---|
| IN_CLOSE_WRITE | File opened for writing was closed. Fires once per close; prefer this over IN_MODIFY for config-reload triggers. |
| IN_MOVED_TO | File was renamed into the watched directory. Required when the writer does an atomic temp-file-plus-rename. |
| IN_MODIFY | File content was modified. Fires on every write(2) call, not per-close. Noisy and wrong for watching targets of atomic renames. |
| IN_CREATE | File or directory was created inside a watched directory. |
| IN_DELETE | File or directory inside a watched directory was deleted. |
| IN_Q_OVERFLOW | Event queue overflowed; events were dropped. The kernel queues exactly one of these then discards until the queue drains. Always check for this flag or you have a silent failure mode. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| ENOSPC | The per-user watch limit (/proc/sys/fs/inotify/max_user_watches) was reached. Raise the limit in /etc/sysctl.d/. |
| EACCES | Read permission denied on the path. |
| ENOENT | The path does not exist. Watches on missing paths must be re-added after creation. |
Example
#include <sys/inotify.h>
#include <unistd.h>
int fd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
int wd = inotify_add_watch(fd, "/etc/app.conf",
IN_CLOSE_WRITE | IN_MOVED_TO);
char buf[4096]
__attribute__((aligned(__alignof__(struct inotify_event))));
ssize_t n = read(fd, buf, sizeof(buf));
struct inotify_event *ev = (struct inotify_event *)buf;
if (ev->mask & IN_Q_OVERFLOW) {
/* queue overflowed: events were dropped, resync state */
}Trimmed from the full walkthrough in inotify_add_watch(2): filesystem events without the poll loop.
BSD equivalent
FreeBSD uses kqueue(2) + kevent(2) with EVFILT_VNODE. Watches are per-fd: open the file or directory, then register with kevent. NOTE_WRITE, NOTE_RENAME, NOTE_DELETE, and NOTE_ATTRIB are the main filter flags. Overflow is explicit and per-event rather than a single queue-full signal. More granular, fewer surprises.
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
