**问题:在使用fsnotify 做系统文件监控时,出现no space left on device**
如下图:
![image.png](https://static.studygolang.com/190116/b1e41e5f4781a0e3bede8f18c5f42c14.png)
第二次,切换监控的文件顺序出现如下图
![image.png](https://static.studygolang.com/190116/1282bdda6c9ebe9b343616eca1a29c28.png)
**代码:**
```
package main
import (
"path/filepath"
"os"
"fmt"
"log"
"time"
"github.com/fsnotify/fsnotify"
)
type empty struct {
}
type Filemon struct {
watch *fsnotify.Watcher
r chan empty
}
//监控目录
func (w *Filemon) watchDir(dir string) {
//通过Walk来遍历目录下的所有子目录
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
//这里判断是否为目录,只需监控目录即可
//目录下的文件也在监控范围内,不需要我们一个一个加
if info.IsDir() {
path, err := filepath.Abs(path)
if err != nil {
return err;
}
err = w.watch.Add(path)
if err != nil {
return err;
}
fmt.Println("监控 : ", path)
}
return nil;
});
go func() {
for {
select {
case ev := <-w.watch.Events:
{
if ev.Op&fsnotify.Create == fsnotify.Create {
fmt.Println("创建文件 : ", ev.Name)
//这里获取新创建文件的信息,如果是目录,则加入监控中
fi, err := os.Stat(ev.Name)
if err == nil && fi.IsDir() {
w.watch.Add(ev.Name)
fmt.Println("添加监控 : ", ev.Name);
}
}
if ev.Op&fsnotify.Write == fsnotify.Write {
fmt.Println("写入文件 : ", ev.Name)
}
if ev.Op&fsnotify.Remove == fsnotify.Remove {
fmt.Println("删除文件 : ", ev.Name)
//如果删除文件是目录,则移除监控
fi, err := os.Stat(ev.Name);
if err == nil && fi.IsDir() {
w.watch.Remove(ev.Name);
fmt.Println("删除监控 : ", ev.Name)
}
}
if ev.Op&fsnotify.Rename == fsnotify.Rename {
fmt.Println("重命名文件 : ", ev.Name)
//如果重命名文件是目录,则移除监控
//注意这里无法使用os.Stat来判断是否是目录了
//因为重命名后,go已经无法找到原文件来获取信息了
//所以这里就简单粗爆的直接remove好了
w.watch.Remove(ev.Name);
}
if ev.Op&fsnotify.Chmod == fsnotify.Chmod {
fmt.Println("修改权限 : ", ev.Name)
//scanMonChan<-ev.Name
}
}
case err := <-w.watch.Errors:
{
fmt.Println("error : ", err)
return;
}
case <-w.r:
log.Println("exit")
}
}
}()
}
func NewFilemon(path string) (*Filemon){
watch, _ := fsnotify.NewWatcher()
w := &Filemon{
watch: watch,
r:make(chan empty),
}
before:=time.Now().Unix()
w.watchDir(path) // 监控扫描入口
// go scanFilemon() // 检测修改的文件,并进行扫描
after:=time.Now().Unix()
log.Println("执行时间: ", after-before)
return w
}
func (self *Filemon) Close(){
self.watch.Close()
close(self.r) //这里应该存在问题
}
var count int64
//添加监控文件夹--递归检测目录下的所有文件
func (self *Filemon)AddMonDir(dir string){
filepath.Walk(dir, func(path string,info os.FileInfo,err error) error {
//这里判断是否为目录,只需监控目录即可
//目录下的文件也在监控范围内,不需要我们一个一个加
if info.IsDir() {
path, err := filepath.Abs(path)
if err != nil {
return err
}
err = self.watch.Add(path)
if err != nil {
fmt.Println(err,path)
return err
}
count++
fmt.Println("监控: ", path,count)
}
return nil
})
}
func main(){
filemon:=NewFilemon("/opt")
filemon.AddMonDir("/root")
filemon.AddMonDir("/usr")
filemon.AddMonDir("/lib")
filemon.AddMonDir("/var")
filemon.AddMonDir("/tmp")
defer filemon.Close()
select {}
}
```
如果不方便复制代码,此处可复制:
https://gitee.com/JGbooks/go/blob/master/22_fsnotify/mian.go
### 求解这是什么原因,这个程序出处找不到了。请见谅。
https://askubuntu.com/questions/353041/how-to-change-value-of-proc-sys-fs-inotify-max-user-watches
#4
更多评论
<a href="/user/chenph" title="@chenph">@chenph</a> 不是磁盘满了,linux 资源足够。磁盘使用了%25 不到
#2