久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      golang怎么實(shí)現(xiàn)文件監(jiān)控

      在golang中,可以利用fsnotify來實(shí)現(xiàn)文件監(jiān)控。fsnotify是go語言跨平臺(tái)文件系統(tǒng)監(jiān)控工具,實(shí)現(xiàn)了一個(gè)基于channel的、跨平臺(tái)的實(shí)時(shí)監(jiān)聽接口;golang通過fsnotify可監(jiān)控文件,并通過文件變化重啟程序。

      golang怎么實(shí)現(xiàn)文件監(jiān)控

      本教程操作環(huán)境:windows10系統(tǒng)、GO 1.18版本、Dell G3電腦。

      在golang中,可以利用fsnotify來實(shí)現(xiàn)文件監(jiān)控。

      golang 通過fsnotify監(jiān)控文件,并通過文件變化重啟程序。

      go語言跨平臺(tái)文件系統(tǒng)監(jiān)控工具 — fsnotify

      在 linux 內(nèi)核中,Inotify 是一種用于通知用戶空間程序文件系統(tǒng)變化的機(jī)制。它監(jiān)控文件系統(tǒng)的變化,如文件新建、修改、刪除等,并可以將相應(yīng)的事件通知給應(yīng)用程序。

      Inotify 既可以監(jiān)控文件,也可以監(jiān)控目錄。當(dāng)監(jiān)控目錄時(shí),它可以同時(shí)監(jiān)控目錄及目錄中的各子目錄及文件。Golang 的標(biāo)準(zhǔn)庫 syscall 實(shí)現(xiàn)了該機(jī)制。

      為了進(jìn)一步擴(kuò)展和抽象, github.com/fsnotify/fsnotify 包實(shí)現(xiàn)了一個(gè)基于 channel 的、跨平臺(tái)的實(shí)時(shí)監(jiān)聽接口。

      fsnotify工具的使用

      一、下載我們需要的包

      go get github.com/fsnotify/fsnotify
      登錄后復(fù)制

      二、使用fsnotify監(jiān)控文件

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      package main;

      import (

      "github.com/fsnotify/fsnotify"

      "log"

      "fmt"

      )

      func main() {

      //創(chuàng)建一個(gè)監(jiān)控對象

      watch, err := fsnotify.NewWatcher();

      if err != nil {

      log.Fatal(err);

      }

      defer watch.Close();

      //添加要監(jiān)控的對象,文件或文件夾

      err = watch.Add("./tmp");

      if err != nil {

      log.Fatal(err);

      }

      //我們另啟一個(gè)goroutine來處理監(jiān)控對象的事件

      go func() {

      for {

      select {

      case ev := <-watch.Events:

      {

      //判斷事件發(fā)生的類型,如下5種

      // Create 創(chuàng)建

      // Write 寫入

      // Remove 刪除

      // Rename 重命名

      // Chmod 修改權(quán)限

      if ev.Op&fsnotify.Create == fsnotify.Create {

      log.Println("創(chuàng)建文件 : ", ev.Name);

      }

      if ev.Op&fsnotify.Write == fsnotify.Write {

      log.Println("寫入文件 : ", ev.Name);

      }

      if ev.Op&fsnotify.Remove == fsnotify.Remove {

      log.Println("刪除文件 : ", ev.Name);

      }

      if ev.Op&fsnotify.Rename == fsnotify.Rename {

      log.Println("重命名文件 : ", ev.Name);

      }

      if ev.Op&fsnotify.Chmod == fsnotify.Chmod {

      log.Println("修改權(quán)限 : ", ev.Name);

      }

      }

      case err := <-watch.Errors:

      {

      log.Println("error : ", err);

      return;

      }

      }

      }

      }();

      //循環(huán)

      select {};

      }

      測試結(jié)果如下:

      golang怎么實(shí)現(xiàn)文件監(jiān)控

      我們在tmp目錄下的操作都被捕捉到了,但是fsnotify有一個(gè)問題,它無法遞歸的幫我們捕捉子目錄、孫子目錄的操作事件,這需要我們自已來實(shí)現(xiàn)。

      還有一個(gè)問題就是當(dāng)們修改文件夾名稱時(shí),fsnotify中event.Name仍然是原來的文件名,這就需要我們在重命名事件中,先移除之前的監(jiān)控,然后添加新的監(jiān)控。

      修改如下:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      package main;

      import (

      "github.com/fsnotify/fsnotify"

      "fmt"

      "path/filepath"

      "os"

      )

      type Watch struct {

      watch *fsnotify.Watcher;

      }

      //監(jiān)控目錄

      func (w *Watch) watchDir(dir string) {

      //通過Walk來遍歷目錄下的所有子目錄

      filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {

      //這里判斷是否為目錄,只需監(jiān)控目錄即可

      //目錄下的文件也在監(jiān)控范圍內(nèi),不需要我們一個(gè)一個(gè)加

      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("監(jiān)控 : ", path);

      }

      return nil;

      });

      go func() {

      for {

      select {

      case ev := <-w.watch.Events:

      {

      if ev.Op&fsnotify.Create == fsnotify.Create {

      fmt.Println("創(chuàng)建文件 : ", ev.Name);

      //這里獲取新創(chuàng)建文件的信息,如果是目錄,則加入監(jiān)控中

      fi, err := os.Stat(ev.Name);

      if err == nil && fi.IsDir() {

      w.watch.Add(ev.Name);

      fmt.Println("添加監(jiān)控 : ", ev.Name);

      }

      }

      if ev.Op&fsnotify.Write == fsnotify.Write {

      fmt.Println("寫入文件 : ", ev.Name);

      }

      if ev.Op&fsnotify.Remove == fsnotify.Remove {

      fmt.Println("刪除文件 : ", ev.Name);

      //如果刪除文件是目錄,則移除監(jiān)控

      fi, err := os.Stat(ev.Name);

      if err == nil && fi.IsDir() {

      w.watch.Remove(ev.Name);

      fmt.Println("刪除監(jiān)控 : ", ev.Name);

      }

      }

      if ev.Op&fsnotify.Rename == fsnotify.Rename {

      fmt.Println("重命名文件 : ", ev.Name);

      //如果重命名文件是目錄,則移除監(jiān)控

      //注意這里無法使用os.Stat來判斷是否是目錄了

      //因?yàn)橹孛螅琯o已經(jīng)無法找到原文件來獲取信息了

      //所以這里就簡單粗爆的直接remove好了

      w.watch.Remove(ev.Name);

      }

      if ev.Op&fsnotify.Chmod == fsnotify.Chmod {

      fmt.Println("修改權(quán)限 : ", ev.Name);

      }

      }

      case err := <-w.watch.Errors:

      {

      fmt.Println("error : ", err);

      return;

      }

      }

      }

      }();

      }

      func main() {

      watch, _ := fsnotify.NewWatcher()

      w := Watch{

      watch: watch,

      }

      w.watchDir("./tmp");

      select {};

      }

      測試結(jié)果如下:

      golang怎么實(shí)現(xiàn)文件監(jiān)控

      經(jīng)過上面的例子,我們通過fsnotify來寫一個(gè)監(jiān)控配置文件,如果配置文件有修改,就重新啟動(dòng)服務(wù)。

      我們先寫一個(gè)可以運(yùn)行的exe程序,server.go代碼如下:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      package main;

      import (

      "io/ioutil"

      "log"

      "encoding/json"

      "net"

      "fmt"

      "os"

      "os/signal"

      )

      const (

      confFilePath = "./conf/conf.json";

      )

      //我們這里只是演示,配置項(xiàng)只設(shè)置一個(gè)

      type Conf struct {

      Port int `json:port`;

      }

      func main() {

      //讀取文件內(nèi)容

      data, err := ioutil.ReadFile(confFilePath);

      if err != nil {

      log.Fatal(err);

      }

      var c Conf;

      //解析配置文件

      err = json.Unmarshal(data, &c);

      if err != nil {

      log.Fatal(err);

      }

      //根據(jù)配置項(xiàng)來監(jiān)聽端口

      lis, err := net.Listen("tcp", fmt.Sprintf(":%d", c.Port));

      if err != nil {

      log.Fatal(err);

      }

      log.Println("server start");

      go func() {

      ch := make(chan os.Signal);

      //獲取程序退出信號

      signal.Notify(ch, os.Interrupt, os.Kill);

      <-ch;

      log.Println("server exit");

      os.Exit(1);

      }();

      for {

      conn, err := lis.Accept();

      if err != nil {

      continue;

      }

      go func(conn net.Conn) {

      defer conn.Close();

      conn.Write([]byte("hellon"));

      }(conn);

      }

      }

      使用如下命令,編譯成exe文件

      1

      > go build server.go

      監(jiān)控文件fsnotify3.go代碼如下:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      95

      96

      97

      98

      99

      100

      101

      102

      103

      104

      105

      106

      107

      108

      109

      110

      111

      package main;

      import (

      "github.com/fsnotify/fsnotify"

      "log"

      "fmt"

      "os/exec"

      "regexp"

      "strconv"

      "bytes"

      "errors"

      "os"

      "path/filepath"

      )

      const (

      confFilePath = "./conf";

      )

      //獲取進(jìn)程ID

      func getPid(processName string) (int, error) {

      //通過wmic process get name,processid | findstr server.exe獲取進(jìn)程ID

      buf := bytes.Buffer{};

      cmd := exec.Command("wmic", "process", "get", "name,processid");

      cmd.Stdout = &buf;

      cmd.Run();

      cmd2 := exec.Command("findstr", processName);

      cmd2.Stdin = &buf;

      data, _ := cmd2.CombinedOutput();

      if len(data) == 0 {

      return -1, errors.New("not find");

      }

      info := string(data);

      //這里通過正則把進(jìn)程id提取出來

      reg := regexp.MustCompile(`[0-9]+`);

      pid := reg.FindString(info);

      return strconv.Atoi(pid);

      }

      //啟動(dòng)進(jìn)程

      func startProcess(exePath string, args []string) error {

      attr := &os.ProcAttr{

      //files指定新進(jìn)程繼承的活動(dòng)文件對象

      //前三個(gè)分別為,標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤輸出

      Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},

      //新進(jìn)程的環(huán)境變量

      Env: os.Environ(),

      }

      p, err := os.StartProcess(exePath, args, attr);

      if err != nil {

      return err;

      }

      fmt.Println(exePath, "進(jìn)程啟動(dòng)");

      p.Wait();

      return nil;

      }

      func main() {

      //創(chuàng)建一個(gè)監(jiān)控對象

      watch, err := fsnotify.NewWatcher();

      if err != nil {

      log.Fatal(err);

      }

      defer watch.Close();

      //添加要監(jiān)控的文件

      err = watch.Add(confFilePath);

      if err != nil {

      log.Fatal(err);

      }

      //我們另啟一個(gè)goroutine來處理監(jiān)控對象的事件

      go func() {

      for {

      select {

      case ev := <-watch.Events:

      {

      //我們只需關(guān)心文件的修改

      if ev.Op&fsnotify.Write == fsnotify.Write {

      fmt.Println(ev.Name, "文件寫入");

      //查找進(jìn)程

      pid, err := getPid("server.exe");

      //獲取運(yùn)行文件的絕對路徑

      exePath, _ := filepath.Abs("./server.exe")

      if err != nil {

      //啟動(dòng)進(jìn)程

      go startProcess(exePath, []string{});

      } else {

      //找到進(jìn)程,并退出

      process, err := os.FindProcess(pid);

      if err == nil {

      //讓進(jìn)程退出

      process.Kill();

      fmt.Println(exePath, "進(jìn)程退出");

      }

      //啟動(dòng)進(jìn)程

      go startProcess(exePath, []string{});

      }

      }

      }

      case err := <-watch.Errors:

      {

      fmt.Println("error : ", err);

      return;

      }

      }

      }

      }();

      //循環(huán)

      select {};

      }

      我們運(yùn)行fsnotify3.go文件來監(jiān)控我們的配置文件

      golang怎么實(shí)現(xiàn)文件監(jiān)控

      通過上面的圖可以看到,當(dāng)我們修改配置文件中的端口號時(shí),會(huì)先kill掉進(jìn)程,然后再啟動(dòng)一個(gè)進(jìn)程。

      golang怎么實(shí)現(xiàn)文件監(jiān)控

      推薦學(xué)習(xí):Golang教程

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號