[Go] 跨平台文件系统监控工具 fsnotify 应用举例
项目地址:https://github.com/fsnotify/fsnotify
fsnotify 能监控指定文件夹内 文件的修改情况,如 文件的 增加、删除、修改、重命名等操作。
官方给出了以下注意事项:
When a file is moved to another directory is it still being watched?
No (it shouldn't be, unless you are watching where it was moved to).
When I watch a directory, are all subdirectories watched as well?
No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap #18).
Do I have to watch the Error and Event channels in a separate goroutine?
As of now, yes. Looking into making this single-thread friendly (see howeyc #7)
Why am I receiving multiple events for the same file on OS X?
Spotlight indexing on OS X can result in multiple events (see howeyc #62). A temporary workaround is to add your folder(s) to the Spotlight Privacy settings until we have a native FSEvents implementation (see #11).
How many files can be watched at once?
There are OS-specific limits as to how many watches can be created:
- Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error.
- BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error.
最为注意的一点是:
文件夹中的子文件夹,还需自己去添加监控,fsnotify 本身不提供递归循环监控功能!
应用举例
package main import ( "github.com/fsnotify/fsnotify" "log" "runtime" ) func main() { // 监控路径列表 paths := []string{ "/Users/jianbao/GoglandProjects/fiisoo/src/test/ch0", "/Users/jianbao/GoglandProjects/fiisoo/src/test/ch1", } watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatalf("Failed to create watcher: %s", err) } defer watcher.Close() exit := make(chan bool) go func() { for { select { case e := <-watcher.Events: log.Println("修改文件:" + e.Name) log.Println("修改类型:" + e.Op.String()) case err := <-watcher.Errors: log.Printf("Watcher error: %s\n", err.Error()) // No need to exit here } } }() log.Println("Initializing watcher...") for _, path := range paths { log.Printf("Watching: %s\n", path) err = watcher.Add(path) if err != nil { log.Fatalf("Failed to watch directory: %s", err) } } <-exit // 用来 阻塞应用不退出,只能通过“杀死进程”的方式退出,如 按住 Ctrl + C 快捷键强制推出 runtime.Goexit() }