真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

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

本篇內(nèi)容介紹了“golang如何實(shí)現(xiàn)文件監(jiān)控”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

我們提供的服務(wù)有:成都做網(wǎng)站、成都網(wǎng)站制作、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、殷都ssl等。為近千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的殷都網(wǎng)站制作公司

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

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

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

go語(yǔ)言跨平臺(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)庫(kù) syscall 實(shí)現(xiàn)了該機(jī)制。

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

fsnotify工具的使用

一、下載我們需要的包

go get github.com/fsnotify/fsnotify

二、使用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)控對(duì)象

   watch, err := fsnotify.NewWatcher();

   if err != nil {

       log.Fatal(err);

   }

   defer watch.Close();

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

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

   if err != nil {

       log.Fatal(err);

   }

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

   go func() {

       for {

           select {

           case ev := <-watch.Events:

               {

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

                   // Create 創(chuàng)建

                   // Write 寫(xiě)入

                   // 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("寫(xiě)入文件 : ", 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 {};

}

測(cè)試結(jié)果如下:

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

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

還有一個(gè)問(wèn)題就是當(dāng)們修改文件夾名稱時(shí),fsnotify中event.Name仍然是原來(lái)的文件名,這就需要我們?cè)谥孛录?,先移除之前的監(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) {

   //通過(guò)Walk來(lái)遍歷目錄下的所有子目錄

   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("寫(xiě)入文件 : ", 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)控

                       //注意這里無(wú)法使用os.Stat來(lái)判斷是否是目錄了

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

                       //所以這里就簡(jiǎn)單粗爆的直接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 {};

}

測(cè)試結(jié)果如下:

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

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

我們先寫(xiě)一個(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)來(lái)監(jiān)聽(tīng)端口

   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);

       //獲取程序退出信號(hào)

       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("hello\n"));

       }(conn);

   }

}

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

1

> go build server.go

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

    • <noframes id="e4usy"><tbody id="e4usy"></tbody></noframes>

      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) {

         //通過(guò)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);

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

         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)文件對(duì)象

             //前三個(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)控對(duì)象

         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來(lái)處理監(jiān)控對(duì)象的事件

         go func() {

             for {

                 select {

                 case ev := <-watch.Events:

                     {

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

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

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

                             //查找進(jìn)程

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

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

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

                             if err != nil {

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

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

                             } else {


      網(wǎng)站名稱:golang如何實(shí)現(xiàn)文件監(jiān)控
      瀏覽地址:http://weahome.cn/article/gsogos.html

      在線咨詢

      微信咨詢

      電話咨詢

      028-86922220(工作日)

      18980820575(7×24)

      提交需求

      返回頂部