行业知识
go linux监测文件变化
2026-11-08 19:06:26
来源:互联网转载
go linux监测文件变化
���件改变内容有两种方式,效果一样,但执行方式有区别:
- 直接打开文件改,现在很多编辑器都是这样操作的
- 先删除原来的,再新创建写入一个替代原来的。比如vi/vim.这种方式会打断linux inotify原有的监测(就好比你有一部手机,一个人走过来给你砸了,再递给你一部同型号配置,内容备份了你原来的手机,但是新下载了个app。这时候你使用上用不出差别,但是它已经不是你原来的手机了).遇到这种情况时我们需要判断是否文件还存在,存在说明就是上述情况,然后需要重新监听文件状态
go linux监测文件变化,靠系统调用inotify.
演示代码
package mainimport ("errors""fmt""log""os""os/signal""strings""sync""syscall""unsafe")type FileLink struct {c chan int64filename string}type FileWatcher struct {linkmap map[int32]FileLinklink map[string]int32resource_mu sync.Mutexfd int}const WATCH_FLAG = syscall.IN_MODIFY | syscall.IN_CLOSE_WRITE// 重新监听文件状态func rewatch(fw *FileWatcher, wd *syscall.InotifyEvent) bool {finfo := fw.linkmap[wd.Wd]if _, err := os.Stat(finfo.filename); err != nil {fmt.Fprintln(os.Stderr, "not found "+finfo.filename+" "+err.Error())return false}fw.resource_mu.Lock()defer fw.resource_mu.Unlock()delete(fw.linkmap, wd.Wd)fmt.Println("rewatch " + finfo.filename)wid, err := syscall.InotifyAddWatch(fw.fd, finfo.filename, WATCH_FLAG)if wid 0 {ans = append(ans, "modify")}if status&syscall.IN_CLOSE_WRITE > 0 {ans = append(ans, "close_write")}return strings.Join(ans, " ")}func (s *FileWatcher) AddWatch(filename_list ...string) ([]s.resource_mu.Lock()defer s.resource_mu.Unlock()var (errlist []errorchanlist []wd, err := syscall.InotifyAddWatch(s.fd, name, WATCH_FLAG)if err != nil {errlist = append(errlist, err)} else {s.linkmap[int32(wd)] = FileLink{c: make(chan int64, 1), filename: name}s.link[name] = int32(wd)chanlist = append(chanlist, s.linkmap[int32(wd)].c)}}if len(errlist) 0 {return chanlist, errors.Join(errlist...)}return chanlist, nil}func (s *FileWatcher) Delete(filename_list ...string) {s.resource_mu.Lock()defer s.resource_mu.Unlock()for _, name := range filename_list {if wd, ok := s.link[name]; ok {syscall.InotifyRmWatch(s.fd, uint32(wd))close(s.linkmap[wd].c)delete(s.link, name)delete(s.linkmap, wd)}}}func (s *FileWatcher) Close() error {return syscall.Close(s.fd)}func NewFileWatcher() (*FileWatcher, error) {var filewatcher FileWatcherfilewatcher.linkmap = make(map[int32]FileLink)filewatcher.link = make(map[string]int32)var err errorfilewatcher.fd, err = syscall.InotifyInit()if err != nil {return nil, err}go func() {var (buff []byte = make([]byte, 1size, err = syscall.Read(filewatcher.fd, buff)if err == nil {if size