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"######### #######"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 !
#
return
err;
# ##
#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">
##
if
ev.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( ## 所》
##}
if
ev.Op&fsnotify.Chmod ==
fmt。 Println(
"權限: "
##, ev.Name);
修改 ”
}
##
{
fmt.Println(
"錯誤: "
,錯誤);
#}
#
}
#
##
}();
#}
##func main() {
watch, _ := fsnotify.NewWatcher()
#w := 觀看{
觀看:觀看,
}
w.watchDir(
"./tmp"
);
# ########選擇 {};##########
測試結果如下:
經過上面的例子,我們透過fsnotify來寫一個監控設定文件,如果設定檔有修改,就重新啟動服務。
我們先寫一個可以執行的exe程序,server.go程式碼如下:
1
2
3
4
5
6
#7
8 ##9#10111213141516#17181920#2122#23 #24252627#28#29#30# 31323334#35#36#37#38 3940414243444546474849505152535455565758
|
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);
if err != 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 ##1011121314#151617
18192021#22#23#24# 25262728#29#30#31##32 333435363738394041424344454647484950515253 54555657585960
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"
「位元組」
「錯誤」
#
"路徑/檔案路徑"
#
#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
fmt.Println(ev.Name, ##"檔案寫入" #);
# //尋找程序
, ##.
#
//獲取 exePath, _ := filepath.Abs (
)
{
##
#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 {};
}
|
#我們執行fsnotify3.go檔案來監控我們的設定檔
############透過上面的圖可以看到,當我們修改設定檔中的連接埠號碼時,會先kill掉進程,然後再啟動一個進程。 ###############推薦學習:###Golang教學############