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

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

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

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

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

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

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

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

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

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

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

為了進一步擴展和抽象, github.com/fsnotify/fsnotify 包實現(xiàn)了一個基于 channel 的、跨平臺的實時監(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)建一個監(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);

}

//我們另啟一個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怎么實現(xiàn)文件監(jiān)控

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

還有一個問題就是當們修改文件夾名稱時,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),不需要我們一個一個加

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來判斷是否是目錄了

//因為重命名后,go已經(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怎么實現(xiàn)文件監(jiān)控

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

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

)

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

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ù)配置項來監(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";

)

//獲取進程ID

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

//通過wmic process get name,processid | findstr server.exe獲取進程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);

//這里通過正則把進程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},

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

Env: os.Environ(),

}

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

if err != nil {

return err;

}

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

p.Wait();

return nil;

}

func main() {

//創(chuàng)建一個監(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);

}

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

go func() {

for {

select {

case ev := <-watch.Events:

{

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

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

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

//查找進程

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

//獲取運行文件的絕對路徑

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

if err != nil {

//啟動進程

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

} else {

//找到進程,并退出

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

if err == nil {

//讓進程退出

process.Kill();

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

}

//啟動進程

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

}

}

}

case err := <-watch.Errors:

{

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

return;

}

}

}

}();

//循環(huán)

select {};

}

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

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

通過上面的圖可以看到,當我們修改配置文件中的端口號時,會先kill掉進程,然后再啟動一個進程。

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

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

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
又爽又刺激免费男女视频| 久久精品成人免费国产片| 中国女人内射6XXXXX| 日韩人妻无码视频| 激情 小说 亚洲 图片 伦| 亚洲欧洲成人A∨在线观看| 人妻少妇精品一区二区三区| 成熟人妻换╳╳╳╳Ⅹ| 亚洲色成人网站WWW永久下载| 日韩视频中文字幕精品偷拍| 看全色黄大色大片免费久久| 吃了继兄开的药后我做的梦更长了| 人妻少妇精品无码专区| 高清毛茸茸的中国少妇| 亚洲国产精品久久久久久久| 精品无人区卡一卡二卡三乱码| 亚洲碰碰人人AV熟女天堂| 日日AV拍夜夜添久久免费| 妺妺窝人体色www婷婷| 国产成人无码3000部| 亚洲人成网亚洲欧洲无码久久| 免费国产成人高清在线视频| 丰满熟妇性ⅩXXOOO69| 亚洲国产综合精品 在线 一区| 人妻人人澡人人添人人爽 | 国产精品爽爽VA在线观看网站| 亚洲国产成人精品无码区在线| 女人露P毛视频·WWW| 国产农村乱子伦精品视频| 亚洲一级 片内射无码| 首页 综合国产 亚洲 丝袜日本| 狠狠色丁香久久婷婷综合_中| 好男人影视官网在线WWW| 久久久久国色AV免费看图片| 国产精品99久久精品爆乳| 精品高潮呻吟99AV无码| 欧美激情内射喷水高潮| 无遮挡又色又刺激的视频黄| 又大又粗弄得我好爽GIF| 第一次处破女01免费观看| 激情欧美日韩一区二区| 欧美爽到高潮漏水大喷视频| 午夜福利1000 92免费| 中文字幕一区二区三区乱码人妻| 国产成人精品综合久久久久| 久久中文字幕AV一区二区不卡| 色狠狠久久AV北条麻妃| 亚洲中文字幕久久精品无码喷水| 成人无码H动漫在线播放| 久久大香伊蕉在人线免费AV| 撒尿PISSINGⅤIDEEO| 亚洲综合小说区图片区| 高清一区二区三区日本久| 久久久精品人妻一区二区三区四| 色五月丁香五月综合五月亚洲| 亚洲综合日韩久久成人AV| 公主很忙(N)甜烟| 美女裸体无遮挡永久免费观看网站| 太多了太满了肚子装不下了| 13岁幼儿3OOO| 国外AV无码精品国产精品| 青草久久久国产线免费| 亚洲美女又黄又爽在线观看| 国产98在线 | 免费| 麻豆精品国产综合久久| 小寡妇一夜要了六次| HD老熟女BBN老淑女| 精品乱码久久久久久中文字幕| 少妇AV一区二区三区无码| 曰韩无码A级成人毛片| 国产午夜精品免费一区二区三区| 秋霞久久国产精品电影院| 亚洲熟女丰满多毛XXXXX| 国产精品99久久免费观看| 欧美成人精品在线| 亚洲亚洲人成综合网络| 国产精品亚洲色婷婷99久久精品| 欧美性受XXXX黑人猛交免费看 | 夜夜揉揉日日人人| 国产麻豆 9L 精品三级站| 人妖CHINESECDTS在线| 伊人久久精品亚洲午夜| 国精产品一区一区三区有限在线| 日文中字乱码一二三区别在哪 | 男生把自己的手放到女生的QQ里| 亚洲国产精品久久久久爰| 国产精品18久久久久久麻辣| 人妻少妇 少妇人妻第一页| 幼儿HIPHOP仙踪林的| 很黄很黄的曰批视频| 他的白月光H1∨1笔趣阁| WWW国产成人免费观看视频| 浪荡受NP纯肉公共场合BL男男 | 韩国av一区二区三区| 天天爱天天做天天爽| 把腿张开老子臊烂你| 迈开腿让我尝一下你的味道一| 亚洲A成人无码网站在线| 国产粉嫩嫩00在线正在播放 | 亚洲熟妇无码另类久久久| 午夜成人鲁丝片午夜精品| 国产高清一区二区三区视频| 欧美日韩精品久久久免费观看 | 九九爱WWW免费人成视频| 挽起裙子迈开腿坐下去的图片高清| 爆乳JUFD汗だく肉感| 欧美人与性动交a欧美精品| 中文字幕乱近親相姦| 久久永久免费人妻精品直播| 亚洲精品无AMM毛片| 国内揄拍国内精品| 无码一区在线视频| 国产23在线 | 传媒麻豆| 日本BBWW高潮BBWR| JEAⅠOUSVUE成熟HD| 女人三A级毛片视频| 55夜色66夜色国产精品视频| 免费看国产曰批40分钟| 伊人久久大香线蕉AV网禁呦| 久久久精品久久久久久96| 亚洲一区二区三区在线播放无码 | 欧美最猛黑人XXXⅩ猛男野外| 中文字幕四区五区六区蜜桃 | 好疼太大了太粗太长了视频| 亚洲AV成人无码久久WWW| 国产又黄又大又粗的视频| 无人高清视频免费观看在线 | 亚洲国产精品成人久久久| 国语做受对白XXXXX在线| 亚洲AV午夜福利精品一区人妖| 国产一区二区精品久久| 亚洲AV无码成人网站WWW| 果冻传媒播放观看免费| 亚洲国产精品无码7777一线| 精品乱码一区内射人妻无码| 亚洲欧美另类视频| 久久天天躁狠狠躁夜夜| 亚洲综合小说区图片区| 麻豆乱码国产一区二区三区| 16—17女人毛片毛片| 欧美性爱AAAAA| 波多野结衣乳喷高潮视频| 日韩精品视频一区二区| 国产成人无码AV| 亚洲AV成人一区二区三区AV| 精品久久久久久中文墓无码| 亚洲综合无码一区二区三区不卡 | 投诉12345最狠的办法| 国产乱子伦高清露脸对白| 亚洲AV无码国产精品久久不卡| 精品久久久无码中文字幕| 一区二区三区AV| 欧美黑人性暴力猛交喷水| 超清少妇爆乳无码av无码专区| 色婷婷亚洲婷婷七月中文字幕| 国产六月婷婷爱在线观看| 亚洲精品嫩草研究院久久| 麻豆精品一区综合AV在线| 八戒福利WWW资源在线观看| 天天玩天天玩天天玩| 黑人欧美一区二区三区4p| 又硬又大又长又粗又深| 热の无码热の有码热の综合| 国产边做边吃奶AⅤ视频免费| 亚洲AV成人精品五区| 久久久久亚洲AV综合仓井空| CHINA末成年VIDEOS| 色噜噜狠狠色综合无码AV天堂| 国产女人天天春夜夜春| 亚洲国产精品无码久久一线| 麻豆视传媒官方直接进入| 被按摩的人妻中文字幕| 无码日韩精品一区二区三区免费| 久久ZYZ资源站无码中文动漫| 99RIAV国产精品视频| 少妇 精69XXXXXx白浆| 好紧真爽喷水高潮视频办公室| 真人性囗交69图片| 少妇极品熟妇人妻| 精品3D动画肉动漫在线无码| 97久久人人超碰超碰窝窝| 私人影院播放器大全| 精品人妻一区二区三区免费| 99久久精品费精品国产一区二| 视频在线一区二区三区| 久久99青青精品免费观看| めんたいさんでぃふぇんすっ甘雨| 无人区码一码二码三码是 | 一区二区三区国产精华护肤品| 人妻蜜と1~4中文字幕月野定规 | 女教师的凌脣教室在线| 国产成人片AⅤ在线观看| 一本色道久久综合亚州精品蜜桃 | 风流老熟女一区二区三区| 亚洲久热无码中文字幕人妖| 免费无码又爽又高潮视频| 久久久久久精品毛片A级蜜桃| 亚洲欧美另类在线观看| 久久婷婷五月综合色高清图片| 啊灬啊灬啊灬快灬高潮了|