首頁 > 後端開發 > Golang > golang怎麼實現文件監控

golang怎麼實現文件監控

青灯夜游
發布: 2023-02-20 10:18:21
原創
4733 人瀏覽過

在golang中,可以利用fsnotify來實現檔案監控。 fsnotify是go語言跨平台檔案系統監控工具,實作了一個基於channel的、跨平台的即時監聽介面;golang透過fsnotify可監控文件,並透過檔案變更重啟程式。

golang怎麼實現文件監控

本教學操作環境:windows10系統、GO 1.18版本、Dell G3電腦。

在golang中,可以利用fsnotify來實現檔案監控。

golang 透過fsnotify監控文件,並透過文件變更重新啟動程式。

go語言跨平台檔案系統監控工具— fsnotify

#在linux 核心中,Inotify 是用來通知用戶空間程序檔案系統變化的機制。它監控檔案系統的變化,如檔案新建、修改、刪除等,並可以將相應的事件通知給應用程式。

Inotify 既可以監控文件,也可以監控目錄。當監控目錄時,它可以同時監控目錄及目錄中的各子目錄及檔案。 Golang 的標準函式庫 syscall 實現了這個機制。

為了進一步擴展和抽象, github.com/fsnotify/fsnotify 套件實現了一個基於 channel 的、跨平台的即時監聽介面。

fsnotify工具的使用

一、下載我們需要的套件

go get github.com/fsnotify/fsnotify
登入後複製

二、使用fsnotify監控檔案

21

1

2

3

##4

##5

#6

7

8

9

10

11

##12

13

14

15

16

#17

18

#19

20

22

23

24

25

26

27

28

2930

31

3233

34

3536

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"#########    #######"fmt"#### ##

)

  

#func main() {

    //建立一個監視物件

    watch, err := fsnotify.NewWatcher();

# #    if err != nil {

##        #log.Fatal(err);

    }#    

defer watch.Close();defer watch.Close();

//新增要監控的對象,檔案或資料夾

    err = watch.Add(

#". /tmp"

);

    

if err != nil {

#        log.Fatal(err);

    

#}

##//我們另啟一個goroutine來處理監控物件的事件

    go func() {

#### #        ######for### ###{############            ###1 ###case### ###ev :=                   以#                    }       == fsnotify.Write {

#                  以##                    }

      emove == fsnotify.Remove {                        

log.Println(

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

}

      name == fsnotify.Rename {

#                        log.Println("重命名文件: "

, ev.Name);

                    }

      Chmod == fsnotify.Chmod {

#                     以                    

}           case

err :=                 為

                    log.Println("error : "    return

;                }##o

#  

        

#}

    

#}();

## |   

    #//循環

    select {};

}

<p>測試結果如下:</p> <p><img src="https://img.php.cn/upload/image/828/616/906/1676858947782180.png" title="1676858947782180.png" alt="golang怎麼實現文件監控"></p> <p>我們在tmp目錄下的操作都被捕捉到了,但是fsnotify有一個問題,它無法遞歸的幫我們捕捉子目錄、孫子目錄的操作事件,這需要我們自已實現。 </p> <p>還有一個問題就是當們修改資料夾名稱時,fsnotify中event.Name仍然是原來的檔案名,這需要我們在重命名事件中,先移除先前的監控,然後再添加新的監控。 </p> <p>修改如下:</p> <table border="0" cellpadding="0" cellspacing="0" class="syntaxhighlighter js"><tbody><tr class="firstRow"> <td class="gutter"> <p class="line number1 index0 alt2">1</p> <p class="line number2 index1 alt1">#2</p> <p class="line number3 index2 alt2">3</p> <p class="line number4 index3 alt1">4</p> <p class="line number5 index4 alt2">5</p> <p class="line number6 index5 alt1">6</p> <p class="line number7 index6 alt2">7</p> <p class="line number8 index7 alt1">8</p> <p class="line number9 index8 alt2">#9</p> <p class="line number10 index9 alt1">#10</p> <p class="line number11 index10 alt2">11</p> <p class="line number12 index11 alt1">12</p> <p class="line number13 index12 alt2">13</p> <p class="line number14 index13 alt1">14</p> <p class="line number15 index14 alt2">15</p> <p class="line number16 index15 alt1">16</p> <p class="line number17 index16 alt2">17</p> <p class="line number18 index17 alt1">18</p> <p class="line number19 index18 alt2">#19</p> <p class="line number20 index19 alt1">20</p> <p class="line number21 index20 alt2">21</p> <p class="line number22 index21 alt1">22</p> <p class="line number23 index22 alt2">23</p> <p class="line number24 index23 alt1">24</p> <p class="line number25 index24 alt2">25</p> <p class="line number26 index25 alt1">#26</p> <p class="line number27 index26 alt2">27</p> <p class="line number28 index27 alt1">28</p> <p class="line number29 index28 alt2">29</p> <p class="line number30 index29 alt1">#30</p> <p class="line number31 index30 alt2">31</p> <p class="line number32 index31 alt1">#32</p> <p class="line number33 index32 alt2"></p> <p class="line number34 index33 alt1"></p> <p class="line number35 index34 alt2"></p> <p class="line number36 index35 alt1"></p> <p class="line number37 index36 alt2"></p> <p class="line number38 index37 alt1"></p> <p class="line number39 index38 alt2"></p> <p class="line number40 index39 alt1"></p> <p class="line number41 index40 alt2"># #33</p> <p class="line number42 index41 alt1">34</p> <p class="line number43 index42 alt2">35</p> <p class="line number44 index43 alt1">36</p> <p class="line number45 index44 alt2">#37</p> <p class="line number46 index45 alt1">#38</p> <p class="line number47 index46 alt2">#39</p> <p class="line number48 index47 alt1"># 40</p> <p class="line number49 index48 alt2">41</p> <p class="line number50 index49 alt1">42</p> <p class="line number51 index50 alt2">43</p> <p class="line number52 index51 alt1">44</p> <p class="line number53 index52 alt2">#45</p> <p class="line number54 index53 alt1">#46</p> <p class="line number55 index54 alt2">#47 </p> <p class="line number56 index55 alt1">48</p> <p class="line number57 index56 alt2">49</p> <p class="line number58 index57 alt1">50</p> <p class="line number59 index58 alt2">#51</p> <p class="line number60 index59 alt1">52</p> <p class="line number61 index60 alt2">53</p> <p class="line number62 index61 alt1">54</p> <p class="line number63 index62 alt2">55</p> <p class="line number64 index63 alt1">56</p> <p class="line number65 index64 alt2">57</p> <p class="line number66 index65 alt1">58</p> <p class="line number67 index66 alt2">59</p>##60<p class="line number68 index67 alt1"></p>61<p class="line number69 index68 alt2"> </p>#62<p class="line number70 index69 alt1"></p>63<p class="line number71 index70 alt2"></p>64<p class="line number72 index71 alt1"></p>65<p class="line number73 index72 alt2"></p>66<p class="line number74 index73 alt1">##67</p> <p class="line number75 index74 alt2">68</p> <p class="line number76 index75 alt1">#69</p> <p class="line number77 index76 alt2">70</p> <p class="line number78 index77 alt1">71</p> <p class="line number79 index78 alt2">72</p> <p class="line number80 index79 alt1">73</p> <p class="line number81 index80 alt2">74</p> <p class="line number82 index81 alt1">75</p> <p class="line number83 index82 alt2">#76</p> <p class="line number84 index83 alt1">77</p> <p class="line number85 index84 alt2">78</p> <p class="line number86 index85 alt1">79</p> <p class="line number87 index86 alt2">#80</p> <p class="line number88 index87 alt1">81</p> </td>#82<td class="code"><div class="container"> <p class="line number1 index0 alt2"><code class="js plain">

################## #83######84######85#######86#######87#######88############## #####package main;############ ### #########import (######

    "github.com/fsnotify/fsnotify"

    #"fmt"

    "path/filepath"

#    "os"

"os"

##)

  

type 觀看 struct {

    

##watch *fsnotify.Watcher ;

}

 

//監控目錄

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

    

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

    

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

    //這裡判斷是否為目錄,只需監控目錄即可

        //目錄下的檔案也在監控範圍內,不需要我們一個一個加

        if info.IsDir() {

      # ##     ##path, err := filepath.Abs​​(path);

            if err !

#                

returnerr;

  # ##            #err = w.watch.Add(path);

          ##                return

#err;# ##  #            fmt.Println(

"監視器: "#, );

##}

        return nil;

    

   #});    

#go func() {

#<p class="line number34 index33 alt1"><code class="js spaces">        for{

           ## ##            

#case

ev := <code class="js keyword">    

##                    

ifev.Op&fsnotify.Cre)          

# fmt.Println(

"建立檔案: "##, ev.Name);              ##  建立文件的訊息,如果是目錄,則加入監控中

                        ##fi, Stat; #                        1

##1              

w .watch.Add(ev.Name);

                          ev.Name);

                        ## 

}#                    if

ev.Op&fsnotify.Write ==        fmt.Println ("寫入檔案: "

, ev.Name);                          

#  ”

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

##ev.Op&fsnotify.Remove ====#notify.Remove {#ev.

                  以#                        ##///若刪除檔案為目錄,則移除監控##  fi, err := os.Stat(ev.Name) ;

                        

#if                 w.watch.Remove(ev.Name);

                   ##, ev.Name);

                            }

                    

#if ev.Op&fsnot           

##fmt.Println(

"重新命名檔案: ", ev.Name);            /如果重新命名檔案是目錄,則移除監控

                      #                        

//因為重複命名後,因為「重複命名」       

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

                       )(

w.watch.Remove( ##                    所》##}

                    ifev.Op&fsnotify.Chmod ==        

fmt。 Println(

"權限: "##, ev.Name);     修改       ”                 

}         

##                {

                    fmt.Println("錯誤: "

,錯誤);

                    

#}#            }

     #  ##    }();

#}

##func main() {

    

watch, _ := fsnotify.NewWatcher()

#w := 觀看{

        

觀看:觀看,

    

}     w.watchDir(

"./tmp"

);# ########選擇 {};##########

測試結果如下:

golang怎麼實現文件監控

經過上面的例子,我們透過fsnotify來寫一個監控設定文件,如果設定檔有修改,就重新啟動服務。

我們先寫一個可以執行的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"##    

"fmt"    

"os"#    

"os/signal"

#)

  

#const (    #confFilePath = "./conf/conf.json"

;

#)

### ### # ##

//我們這裡只是示範,設定項目只設定一個

type Conf struct {

    Port int `json:port`;

}

 

func main( ) {

    //讀取檔案內容

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

    iferr != nil {

        ##      

#log.Fatal(err);

    

}

    #var

c Conf;

    

//解析設定檔

##o    # = json.Unmarshal(data, &c);

    if err != nil {

#        log.Fatal(err);

    #}

    ##}

##    

#//根據設定項目監聽埠

    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);#ch := make(chan os.Signal);

o 和.Kill);        

##        #      

##"server exit"

);

        #####os.Exit(1);#################os.Exit(1);################# ####    ######}();######

    ##for {

        conn, err := lis.Accept();

        #if err != nil {

        #;#       

}

        ### {

            defer conn.Close();

     byte("hello\n"

));        #}(conn);

    }

#}

############### #使用下列指令,編譯成exe檔#####################1##################> ; go build server.go######################

監控檔案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"

#     「日誌」

    「fmt」

    「 os/exec」

    #"regexp"

    #"strconv"

#    

#"strconv"#    

#"strconv"

    

「位元組」

    

「錯誤」

#    

"os"

    

"路徑/檔案路徑"

)

 

#const (

    confFilePath = # "./conf";)

#//取得進程ID

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

    #//透過wmic進程取得name,processid | findstr server.exe取得程序ID

    buf := bytes.Buffer{};    #cmd := exec.Command(

"wmic", "進程"

##,

"取得" ,

"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(######"找不到"#### ##);############    ######}######

    ##info := string(data);

    #//這裡透過正則將進程id提取出來

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

     pid := reg.FindString(info);

    return strconv.Atoi(pid);

#}

  

#//啟動程序

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

    attr := &os.ProcAttr{

      #//files指定新流程繼承的活動檔案物件        

//前三名分別為,標準輸入、標準輸出、標準錯誤輸出

#》

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

##  

##//新流程的環境變數        

Env: os.Environ(),

Env: os.Environ(),

}  

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

if err != nil {

        #        ##      #return err;

    }

    fmt.Println (exePath, "進程啟動"

);

#    p.Wait();

################################################################################################################' #######    ######return### ###nil;############}############ ### #########func main() {############    ######//建立一個監控物件############ ######watch, err := fsnotify.NewWatcher();#############    ######if### ####err != nil {### #########        ######log.Fatal(err);############    ######}######### ###    ######defer watch.Close();#######

    //新增要監控的檔案

    ##err = watch.Add(confFilePath);

    if err != nil {

        log.Fatal(err) ;

    }

    //我們另啟一個goroutine來處理監控對象的事件

    go func() {

         #for{

            select {

         -watch.Events:                {

 #   修改

                    

#if ev.Op&fs            

fmt.Println(ev.Name,

##"檔案寫入"#);            #  //尋找程序

                        ,##. #                        

//獲取    

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

)

                     {                            ##            

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

<p class="line number87 index86 alt2"><code class="js spaces">                        #} #else##           //找出流程,並退出

                           ).                     

》 if

err == nil {

                                                且為

process.Kill();                      ;

                            ##           //啟動程序

                            #go         }

#                    

}           

case## # ###err :=                 }

##      1 }    

}(); 

 

#    

    

#//循環

    

#select {};

}

golang怎麼實現文件監控

golang怎麼實現文件監控

#我們執行fsnotify3.go檔案來監控我們的設定檔
############透過上面的圖可以看到,當我們修改設定檔中的連接埠號碼時,會先kill掉進程,然後再啟動一個進程。 ###############推薦學習:###Golang教學############

以上是golang怎麼實現文件監控的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板