Documentation
¶
Overview ¶
Package fsnotify provides a cross-platform interface for file system notifications.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrNonExistentWatch = errors.New("can't remove non-existent watcher") ErrEventOverflow = errors.New("fsnotify queue overflow") )
Common errors that can be reported by a watcher
Functions ¶
This section is empty.
Types ¶
type Event ¶
type Event struct { // Path to the file or directory. // // Paths are relative to the input; for example with Add("dir") the Name // will be set to "dir/file" if you create that file, but if you use // Add("/path/to/dir") it will be "/path/to/dir/file". Name string // File operation that triggered the event. // // This is a bitmask as some systems may send multiple operations at once. // Use the Event.Has() method instead of comparing with ==. Op Op }
Event represents a file system notification.
type Op ¶
type Op uint32
Op describes a set of file operations.
type Watcher ¶
type Watcher struct { // Events sends the filesystem change events. // // fsnotify can send the following events; a "path" here can refer to a // file, directory, symbolic link, or special files like a FIFO. // // fsnotify.Create A new path was created; this may be followed by one // or more Write events if data also gets written to a // file. // // fsnotify.Remove A path was removed. // // fsnotify.Rename A path was renamed. A rename is always sent with the // old path as [Event.Name], and a Create event will be // sent with the new name. Renames are only sent for // paths that are currently watched; e.g. moving an // unmonitored file into a monitored directory will // show up as just a Create. Similarly, renaming a file // to outside a monitored directory will show up as // only a Rename. // // fsnotify.Write A file or named pipe was written to. A Truncate will // also trigger a Write. A single "write action" // initiated by the user may show up as one or multiple // writes, depending on when the system syncs things to // disk. For example when compiling a large Go program // you may get hundreds of Write events, so you // probably want to wait until you've stopped receiving // them (see the dedup example in cmd/fsnotify). // // fsnotify.Chmod Attributes were changes (never sent on Windows). On // Linux this is also sent when a file is removed (or // more accurately, when a link to an inode is // removed), and on kqueue when a file is truncated. Events chan Event // Errors sends any errors. Errors chan error // contains filtered or unexported fields }
Watcher watches a set of files, delivering events to a channel.
A watcher should not be copied (e.g. pass it by pointer, rather than by value).
Linux notes ¶
When a file is removed a Remove event won't be emitted until all file descriptors are closed, and deletes will always emit a Chmod. For example:
fp := os.Open("file") os.Remove("file") // Triggers Chmod fp.Close() // Triggers Remove
The fs.inotify.max_user_watches sysctl variable specifies the upper limit for the number of watches per user, and fs.inotify.max_user_instances specifies the maximum number of inotify instances per user. Every Watcher you create is an "instance", and every path you add is a "watch".
These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and /proc/sys/fs/inotify/max_user_instances
To increase them you can use sysctl or write the value to the /proc file:
# Default values on Linux 5.18 sysctl fs.inotify.max_user_watches=124983 sysctl fs.inotify.max_user_instances=128
To make the changes persist on reboot edit /etc/sysctl.conf or /usr/lib/sysctl.d/50-default.conf (on some systemd systems):
fs.inotify.max_user_watches=124983 fs.inotify.max_user_instances=128
Reaching the limit will result in a "no space left on device" or "too many open files" error.
kqueue notes (macOS, BSD) ¶
kqueue requires opening a file descriptor for every file that's being watched; so if you're watching a directory with five files then that's six file descriptors. You will run in to your system's "max open files" limit faster on these platforms.
The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to control the maximum number of open files, as well as /etc/login.conf on BSD systems.
macOS notes ¶
Spotlight indexing on macOS can result in multiple events (see #15). A temporary workaround is to add your folder(s) to the "Spotlight Privacy Settings" until we have a native FSEvents implementation (see #11).
func (*Watcher) Add ¶
Add starts monitoring the path for changes.
A path can only be watched once; attempting to watch it more than once will return an error. Paths that do not yet exist on the filesystem cannot be added. A watch will be automatically removed if the path is deleted.
A path will remain watched if it gets renamed to somewhere else on the same filesystem, but the monitor will get removed if the path gets deleted and re-created.
Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special filesystems (/proc, /sys, etc.) generally don't work.
Watching directories ¶
All files in a directory are monitored, including new files that are created after the watcher is started. Subdirectories are not watched (i.e. it's non-recursive).
Watching files ¶
Watching individual files (rather than directories) is generally not recommended as many tools update files atomically. Instead of "just" writing to the file a temporary file will be written to first, and if successful the temporary file is moved to to destination, removing the original, or some variant thereof. The watcher on the original file is now lost, as it no longer exists.
Instead, watch the parent directory and use [Event.Name] to filter out files you're not interested in. There is an example of this in cmd/fsnotify/file.go
func (*Watcher) Remove ¶
Remove stops monitoring the path for changes.
Directories are always removed non-recursively. For example, if you added /tmp/dir and /tmp/dir/subdir then you will need to remove both.
Removing a path that has not yet been added returns ErrNonExistentWatch.