目录监控fsnotify包测试问题

下边测试的例子中,有文件变化时,case event := <-Watch.Events会触发三次,有用过的朋友能解释一下啊

package main

import (
    "flag"
    "log"
    "os/exec"
    "strings"
    "time"
    //    "sync"
    //    "time"

    "github.com/fsnotify/fsnotify"
)

var (
    sleeptime int
    path      string
    cmd       string
    args      []string
)

func init() {
    flag.IntVar(&sleeptime, "t", 30, "-t=30")
    flag.StringVar(&path, "p", "./", "-p=filepath or dirpath")
    flag.StringVar(&cmd, "c", "", "-c=command")
    str := flag.String("a", "", `-a="args1 args2"`)
    flag.Parse()
    args = strings.Split(*str, " ")
}

func main() {
    Watch, err := fsnotify.NewWatcher()
    if err != nil {
        log.Println("Init monitor error: ", err.Error())
        return
    }
    if err := Watch.Add(path); err != nil {
        log.Println("Add monitor path error: ", path)
        return
    }
    var (
    //        cron bool = false
    //        lock      = new(sync.Mutex)
    )
    for {
        select {
        case event := <-Watch.Events:
            if event.Op&fsnotify.Write == fsnotify.Write {
                log.Printf("Monitor event %s", event.String())
            }

            //            if !cron {
            //                cron = true
            //                go func() {
            //                    T := time.After(time.Second * time.Duration(sleeptime))
            //                    <-T
            //                    if err := call(cmd, args...); err != nil {
            //                        log.Println(err)
            //                    }
            //                    lock.Lock()
            //                    cron = false
            //                    lock.Unlock()
            //                }()
            //            }
        case err := <-Watch.Errors:
            log.Println(err)
            return
        }
    }
}

func call(programe string, args ...string) error {
    cmd := exec.Command(programe, args...)
    buf, err := cmd.Output()
    if err != nil {
        return err
    }
    log.Printf("\n%s\n", string(buf))
    return nil
}
已邀请:

yet

赞同来自: huhuyou2

这个是fsnotify的源码

    if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
        e.Op |= Create
    }
    if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE {
        e.Op |= Remove
    }
    if mask&unix.IN_MODIFY == unix.IN_MODIFY {
        e.Op |= Write
    }
    if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
        e.Op |= Rename
    }
    if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
        e.Op |= Chmod
    }

这是linux的inotify的 inotify_event的事件 适用于 inotify_add_watch mask 与 read 返回的inotify_event中mask

IN_ACCESS   文件被访问
IN_ATTRIB   文件属性发生变化
IN_CLOSE_WRITE  以write方式打开文件并关闭
IN_CLOSE_NOWRITE    以非write方式打开文件并关闭
IN_CREATE   文件或目录被创建
IN_DELETE   文件或目录被删除(被监测的文件夹A中B文件被删除)
IN_DELETE_SELF  被监测的文件或目录被删除(被监测的文件夹A被删除)
IN_MODIFY   文件被修改
IN_MOVE_SELF    被监测的文件或目录移动
IN_MOVED_FROM   文件移出被监测的目录
IN_MOVED_TO 文件移入被监测的目录
IN_OPEN 文件被打开

上述flag的集合

IN_ALL_EVENTS   以上所有flag的集合
IN_MOVE IN_MOVED_TO|IN_MOVED_FROM
IN_CLOSE    IN_CLOSE_WRITE|IN_CLOSE_NOWRITE

不常用的flag

IN_DONT_FOLLOW  不follow符号链接 (since 2.6.15)
IN_EXCL_UNLINK  当文件从监测目中unlink后,则不再报告该文件的相关event,比如监控/tmp使用 (since 2.6.36)
IN_MASK_ADD 追打MASK到被监测的pathname
IN_ONESHOT  只监测一次
IN_ONLYDIR  只监测目录

仅由read返回

IN_IGNORED  inotify_rm_watch,文件被删除或者文件系统被umount
IN_ISDIR    发生事件的是一个目录
IN_Q_OVERFLOW   Event队列溢出
IN_UNMOUNT  文件系统unmount

huhuyou2 - fish

赞同来自:

是的,有的时候是两次,我也遇到了

要回复问题请先登录注册