Go语言搬砖 fsnotify文件系统通知

596 阅读2分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」。

前言

fsnotify是一个文件系统通知的库,当监听的目录或文件发生改变时,可以进行通知

目前支持linux,mac,windows系统

官网: github.com/fsnotify/fs…

使用

demo

该demo来源于官网,会进行主要代码讲解

package main

import (
   "github.com/fsnotify/fsnotify"
   "log"
)

func main() {
   watcher, err := fsnotify.NewWatcher()
   if err != nil {
      log.Fatal(err)
   }
   defer watcher.Close()

   done := make(chan bool)
   go func() {
      for {
         select {
         case event, ok := <-watcher.Events:
            if !ok {
               return
            }
            log.Println("event:", event)
            if event.Op&fsnotify.Write == fsnotify.Write {
               log.Println("modified file:", event.Name)
            }
         case err, ok := <-watcher.Errors:
            if !ok {
               return
            }
            log.Println("error:", err)
         }
      }
   }()

   err = watcher.Add(".")
   if err != nil {
      log.Fatal(err)
   }
   <-done
}
  1. new一个fsnotify实例
  2. 函数结束关闭fsnotify,在main是啥意义的,主要是养成良好code习惯
  3. 创建的done 布尔通道主要为了让进程一直运行,不挂掉
  4. watcher.Add 为监听的目录
  5. 如果目录下有文件发生改变,watcher中就会收到事件或错误,然后输出到控制台
  6. 还能对事件的类型做进一步判断,发生Write事件再输出一次

**运行截图 **

image.png

上述示例中有对Write进行判断,其实还支持Create,Remove,Rename,Chmod等增删改授权等类型的判断

image.png

应用场景

可以在一些重要文件被删除或更改时做监控,类似于被动防御

该库比较有名的是被植入在viper配置中做配置热加载

这里我们也模仿一下viper这种热加载方式。以nginx为例,配置文件更改后自动reload,如果配置文件被删除则停止nginx

package main

import (
   "github.com/fsnotify/fsnotify"
   "os"
   "os/exec"
)

func main() {
   watcher, _ := fsnotify.NewWatcher()
   defer watcher.Close()

   done := make(chan bool)
   go func() {
      for {
         select {
         case event, _ := <-watcher.Events:
            if event.Op&fsnotify.Write == fsnotify.Write {
               args := []string{"reload"}
               shellExec("nginx",args)
            } else if event.Op&fsnotify.Remove == fsnotify.Remove {
               args := []string{"stop"}
               shellExec("nginx",args)
            }
         }
      }
   }()

   _ = watcher.Add("/etc/nginx/conf/nginx.conf")
   <-done
}

func shellExec(nginx string,args []string) {
   cmd := exec.Command(nginx, args...)
   cmd.Stdout = os.Stdout
   cmd.Stderr = os.Stderr

   cmd.Run()
   cmd.Wait()
}

当然除了上述场景,在devops领域还有更多的场景,,,批量管理服务器,或批量管理文件等都是可以的