成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

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

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

在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怎么實(shí)現(xiàn)文件監(jiān)控

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

在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
登錄后復(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)控對(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ā)生的類(lèi)型,如下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)們修改文件夾名稱(chē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)橹孛?,go已經(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("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) {

//通過(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 {

//找到進(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文件來(lái)監(jiān)控我們的配置文件

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

通過(guò)上面的圖可以看到,當(dāng)我們修改配置文件中的端口號(hào)時(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號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
国产乱码一区二区三区| 学渣含着学霸几巴的写作业视频| 人人做人人爽人人爱| 人妻无码不卡中文字幕在线视频| 破外女出血视频全过程| 人人澡人人人妻人人人少妇| 搡BBBB搡BBB搡五十| 天天躁日日躁狠狠躁婷婷高清| 无码人妻一区二区三区免费 | 欧美最猛黑人XXXⅩ猛男视频| 农民人伦一区二区三区| 欧美三级在线播放| 日日噜噜夜夜狠狠视频免费| 无码熟熟妇丰满人妻PORN| 久久久久久久精品国产亚洲| 久久狼人大香伊蕉国产| 免费A级毛片无码视频| 欧美一级 片内射欧美乱强| 女班长给我看她小积积作文| 日本免费一区二区三区最新VR| 人妻无码人妻有码中文字幕| 帅气小鲜肉自慰VIDEO| 亚洲AV无码一期二期三期少妇| 亚洲熟伦熟妇AV无码春| 中文字幕亚洲综合久久综合| 暴躁老阿姨CSGO技巧| 成人三级A视频在线观看| 国产精品普通话国语对白露脸| 精品国产乱码久久久久久1区2区 | 51CG10 吃瓜 爆料| 成人免费无码大片A毛片抽搐| 国产粉嫩馒头无套内在线观看免费| 后Λ式动态后Λ式动态图AV | 精东传媒一二三区进站口| 老师上课没戴奶罩看到奶头| 人妻无码一区二区三区蜜桃视频 | 老妇人高清在线观看免费版| 强开小婷嫩苞又嫩又紧视频韩国 | 青青青伊人色综合久久| 我们还没在书房试过| 夜夜爽77777妓女免费看| S8在线观看成人网站| 夫妇联欢会回不去的夜晚樱花 | 性色AV一区二区三区人妻| 一夲道中文字幕AV高清片| 波多野结衣AⅤ无码一区| 国产无遮挡无码视频免费软件| 老熟女HDXXXX国产喷水| 日韩AV一中美AV一中文字慕| 亚洲国产成人无码网站大全| 94久久国产乱子伦精品免费| 丰满少妇BBWBBW| 久久精品国产99精品亚洲蜜桃| 人妻无码一区二区19P| 亚洲AV成人午夜电影在线观看| 69风韵老熟女口爆吞精| 国产精品爽爽ⅴa在线观看| 麻花传媒MV一二三区别在哪里 | 亚洲暴爽AV人人爽日日碰| CHINA熟妇老熟女HD| 国产在线无码免费网站永久| 女生会把隐私透露给异性朋友 | 熟悉妇人妻av无码毛片| 伊人色综合久久天天五月婷| 短篇公交车高H肉辣全集目录| 久久国产劲爆∧V内射-百度| 人妻天天爽夜夜爽一区二区| 亚洲国产精品久久久就秋霞| 成 人片 黄 色 大 片| 久久精品国产一区二区无码| 青青青国产手线观看视频2019| 亚洲AV无码第一区二区三区| WWXX在线观看免费| 久久精品国产久精久精| 天天摸夜夜添夜夜无码| 中文字幕无码人妻丝袜| 国产偷国产偷亚洲高清人| 男人把大JI巴放进女人有视频| 午夜精品久久久久久久无码| a 成 人小说网站在线观看| 国产无遮挡又黄又爽免费网站| 欧美肉体裸交做爰XXXⅩ性| 亚洲XXX午休国产熟女屁| 成人午夜男女爽爽视频| 乱无码伦视频在线观看| 亚洲AV鲁丝一区二区三区| 波多野结衣片全部电影| 两毫米的小洞你却稳稳命中| 玩弄丰满少妇XXXXX性多毛| AⅤ一区二区三区无卡无码| 教官在我腿间疯狂驰聘视频| 熟女系列丰满熟妇AV| www.五月丁香| 末发育娇小性色XXXXX视频| 亚洲色成人www在线观看| 国产综合18久久久久久| 调教秘书跪趴撅起来打光屁股作文 | 日日摸日日碰夜夜爽无码| FREEMOVIES性中国| 美女扒开腿让男人桶爽| 亚洲日本VA午夜在线影院| 国产真实老熟女无套内射| 玩弄丰满熟妇乱XXXXX性多毛| 成熟丰满熟妇高潮XXXXX视频| 欧美人妻体内射射| 18成禁人视频免费网站| 久久在精品线影院精品国产| 亚洲欧美VR色区| 狠狠色综合网站久久久久久久| 午夜精品久久久久久久| 国产精品久久久久久久久KTV| 少妇高潮毛片免费看| 成人无码视频在线观看| 人妻系列无码专区久久五月天 | 亚洲中文字幕AV无码区| 黑人大性殖器大战欧美白妇| 性欧美XXXX乳| 国产乱码精品一区三上| 午夜在线观看的免费网站| 国产精华最好的产品有哪些| 天堂资源官网在线资源| 国产AV无码专区亚洲版综合| 手机免费AV片在线播放| 国产AV高潮社区| 天堂在\/线中文在线8| 国产成人精品一区二区三区免费| 少妇白浆高潮无码免费区| 国产97色在线 | 免| 少妇粉嫩小泬喷水视频WWW| 公和熄洗澡三级中文字幕| 特黄特色三级在线观看| 国产精品久久久久9999吃药| 无码高潮爽到爆的喷水视频| 国产精品久久久久9999高清| 小荡货奶真大水多好紧视频| 精品亚洲AⅤ在线观看| 日产精品一二三区| 把腿张开老子臊烂你的黄漫| 人妻丰满熟妇AⅤ无码区| 被夫の上司に犯中文字幕| 日产乱码一二三区别免费观看| 大菠萝APP福引导前往| 天堂いっしょにしよ在线| 国产欧美亚洲日韩图片| 亚洲第一狼人天堂网亚洲AV| 精品无人区卡卡卡卡卡二卡三乱码| 亚洲日韩精品欧美一区二区| 久久久久久久精品免费| 中文字幕久久久久人妻| 成人片国产精品亚洲| 欧美三级不卡在线观看| ZOOM与人性ZOOM2区别| 免费A级毛片无码| 1000部又爽又黄无遮挡的视频| 两个领导在车里吃我奶| 国产精品高潮呻吟爱久久AV无码 | 男女啪啪免费观看的网址| 国产精品无码免费专区午夜 | 亚洲暴爽AV人人爽日日碰| 国产精品V欧美精品∨日韩| 色伦专区97中文字幕| 成人AV片无码免费网站| 日本高清在线一区二区三区| 啊灬啊灬啊灬高潮了听书最新章节| 男人激烈吮乳吃奶动态图| 中文字幕AV一区| 清纯JK校花被啪啪AV免费| 凹厕所XXXXBBBB偷拍视频| 人妻少妇中文字幕乱码| 成人网站在线观看丰满少妇电影| 日韩人妻无码一区二区三区久久 | 皇上捏住宫女的巨峰| 亚洲国产精品无码久久青草 | 天堂中文最新版在线中文| 国产喷水1区2区3区咪咪爱AV| 中国VODAFONEWIFI粗| 亚洲AV永久无码精品久久麻豆| 公交车上摸到花蒂进去了视频| 强壮公弄得我次次高潮| 成人区人妻精品一区二| 四虎成人精品在永久免费| 免费看视频高清在线观看| 内射爽无广熟女亚洲| 男女性高爱潮免费网站| 精品久久久久久久久中文字幕| 在线观看国产精选免费| 日日噜噜夜夜爽爽| 娇妻在客厅被朋友玩得呻吟动漫| 91人妻人人爽人人澡人人精品| 视频一区欧美日韩| 久久久国产精品VA麻豆| 插花弄玉小说荔枝很甜作者卿凌| 亚洲AV日韩AV一区谷露| 女人被狂躁高潮啊的视频在线看| 国产成人综合五月天久久| 夜里18款禁用B站大全| 精品无码乱码AV| 韩国三级丰满少妇高潮| 亚洲AV无码一级毛片少妇| 老头的老枪又粗又大|