Dans Golang, vous pouvez utiliser fsnotify pour implémenter la surveillance des fichiers. fsnotify est un outil de surveillance du système de fichiers multiplateforme dans le langage Go, qui implémente une interface de surveillance en temps réel multiplateforme basée sur les canaux ; Golang peut surveiller les fichiers via fsnotify et redémarrer le programme en modifiant les fichiers.
L'environnement d'exploitation de ce tutoriel : système Windows 10, GO version 1.18, ordinateur Dell G3.
Dans Golang, vous pouvez utiliser fsnotify pour implémenter la surveillance des fichiers.
golang surveille les fichiers via fsnotify et redémarre le programme via les modifications de fichiers.
Outil de surveillance du système de fichiers multiplateforme en langage Go - fsnotify
Dans le noyau Linux, Inotify est un mécanisme utilisé pour informer les programmes de l'espace utilisateur des modifications du système de fichiers. Il surveille les modifications du système de fichiers, telles que la création, la modification, la suppression, etc. de fichiers, et peut notifier les applications des événements correspondants.
Inotify peut surveiller à la fois les fichiers et les répertoires. Lors de la surveillance d'un répertoire, il peut surveiller le répertoire ainsi que chaque sous-répertoire et fichier du répertoire en même temps. L'appel système de la bibliothèque standard de Golang implémente ce mécanisme.
Afin d'élargir et d'abstraire davantage, le package github.com/fsnotify/fsnotify implémente une interface de surveillance en temps réel multiplateforme basée sur les canaux.
Utilisation de l'outil fsnotify
1. Téléchargez les packages dont nous avons besoin
go get github.com/fsnotify/fsnotify
Copier après la connexion
2 Utilisez fsnotify pour surveiller les fichiers
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 3 5
36
37
38
39 40
41
42
43
44
45
46
47
48
49
50
5 1 52
53
54
55 56
57
58
59
60
|
paquet principal ; package main;
import (
"github.com/fsnotify/fsnotify"
"log"
"fmt"
🎜🎜 importer ( 🎜🎜 "github.com/fsnotify/fsnotify" code>🎜🎜 "log" 🎜🎜 "fmt" 🎜)
func main() {
watch, err := fsnotify.NewWatcher();
if err != nil {
log.Fatal(err);
}
defer watch.Close();
err = watch.Add( "./tmp" );
if err != nil {
log.Fatal(err);
}
go func() {
for {
select {
case ev :=
{
if ev.Op&fsnotify.Create == fsnotify.Create {
log.Println( "创建文件 : " , 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( "修改权限 : " , ev.Name);
}
}
case err :=
{
log.Println( "error : " , err);
return ;
}
}
}
}();
select {};
}
|
Les résultats du test sont les suivants :
Toutes nos opérations dans le répertoire tmp ont été capturées, mais il y a un problème avec fsnotify. Il ne peut pas nous aider à capturer les événements d'opération des sous-répertoires et des répertoires petits-fils de manière récursive. mis en œuvre par nous-mêmes.
Un autre problème est que lorsque nous modifions le nom du dossier, l'event.Name dans fsnotify est toujours le nom du fichier d'origine, ce qui nous oblige à d'abord supprimer la surveillance précédente, puis à ajouter une nouvelle surveillance dans l'événement rename.
Modifié comme suit :
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 2 6
27
28
29
30 31
32
33
34
35
36
37
38
39
40
41
4 2 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 principal; package main;
import (
🎜🎜 import ( 🎜 "github.com/fsnotify/fsnotify"
"fmt"
"path/filepath"
"os"
)
type Watch struct {
watch *fsnotify.Watcher;
}
func (w *Watch) watchDir(dir string) {
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
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( "监控 : " , path);
}
return nil;
});
go func() {
for {
select {
case ev :=
{
if ev.Op&fsnotify.Create == fsnotify.Create {
fmt.Println( "创建文件 : " , ev.Name);
fi, err := os.Stat(ev.Name);
if err == nil && fi.IsDir() {
w.watch.Add(ev.Name);
fmt.Println( "添加监控 : " , ev.Name);
}
}
if ev.Op&fsnotify.Write == fsnotify.Write {
fmt.Println( "写入文件 : " , ev.Name);
}
if ev.Op&fsnotify.Remove == fsnotify.Remove {
fmt.Println( "删除文件 : " , ev.Name);
fi, err := os.Stat(ev.Name);
if err == nil && fi.IsDir() {
w.watch.Remove(ev.Name);
fmt.Println( "删除监控 : " , ev.Name);
}
}
if ev.Op&fsnotify.Rename == fsnotify.Rename {
fmt.Println( "重命名文件 : " , ev.Name);
w.watch.Remove(ev.Name);
}
if ev.Op&fsnotify.Chmod == fsnotify.Chmod {
fmt.Println( "修改权限 : " , ev.Name);
}
}
case err :=
{
fmt.Println( "error : " , err);
return ;
}
}
}
}();
}
func main() {
watch, _ := fsnotify.NewWatcher()
w := Watch{
watch: watch,
}
w.watchDir( "./tmp" );
select {};
}
|
Les résultats du test sont les suivants :
Après l'exemple ci-dessus, nous utilisons fsnotify pour écrire un fichier de configuration de surveillance. Si le fichier de configuration est modifié, le service sera redémarré.
Nous écrivons d'abord un programme exe qui peut être exécuté. Le code server.go est le suivant :
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
3 7
38
39
40
41 42
43
44
45
46
47
48
49
50
51
52
53 54
5 5
56
57
58
|
package main; package main;
import (
"io/ioutil"
"log"
"encoding/json"
"net"
"fmt"
"os"
"os/signal"
)
const (
confFilePath = "./conf/conf.json" ;
)
🎜🎜 import ( 🎜 🎜 "io/ioutil" 🎜🎜 code>"log" 🎜🎜 "encoding/json" 🎜🎜 "net" 🎜🎜 "fmt" 🎜🎜 "os" 🎜🎜 "os/signal" 🎜🎜) 🎜🎜 🎜🎜<code class="js plain">const ( 🎜🎜 confFilePath = "./conf/conf.json" ; 🎜🎜) code>🎜🎜<code class="js space"> 🎜
type Conf struct {
Port int `json:port`;
}
func main() {
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);
}
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);
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文件
Le code fsnotify3.go du fichier de surveillance est le suivant :
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
4 1
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 909 192939495 96979899100101 102103104105 106 107108109
110
111
|
package main; package main;
import (
"github.com/fsnotify/fsnotify"
"log"
"fmt"
"os/exec"
"regexp"
"strconv"
"bytes"
"errors"
"os"
"path/filepath"
)
const (
confFilePath = "./conf" ;
)
func getPid(processName string) (int, error) {
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" );
}
importer ( 🎜
"github.com/fsnotify/fsnotify" 🎜 "log" 🎜
"fmt" 🎜
"os/exec" 🎜
"regexp" 🎜
"strconv" 🎜
"octets" 🎜
"erreurs" 🎜
"os " 🎜
"chemin/chemin de fichier" 🎜) 🎜
🎜
const ( 🎜
confFilePath = "./conf" ; 🎜) 🎜
🎜
🎜
func getPid(processName string) (int, erreur) { 🎜
🎜
buf := octets. Buffer{}; 🎜
cmd := exec.Command("wmic" , "processus" , "get" , "nom,idprocessus" ); 🎜
cmd.Stdout = &buf; 🎜
cmd.Run(); 🎜
cmd2 : = exec.Command( "findstr" , processName); 🎜
cmd2.Stdin = &buf; 🎜
data, _ := cmd2.CombinedOutput(); 🎜
if len(data) == 0 { 🎜
retour -1, erreurs.Nouveau( "pas trouvé" ); 🎜
} 🎜
info := string(data);
reg := regexp.MustCompile(`[0-9]+`);
pid := reg.FindString(info);
return strconv.Atoi(pid);
}
func startProcess(exePath string, args []string) error {
attr := &os.ProcAttr{
Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
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);
}
go func() {
for {
select {
case ev :=
{
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 :=
{
fmt.Println( "error : " , err);
return ;
}
}
}
}();
select {};
}
|
Nous exécutons le fichier fsnotify3.go pour surveiller notre fichier de configuration
Comme vous pouvez le voir sur l'image ci-dessus, lorsque nous modifions le numéro de port dans le fichier de configuration, le processus sera tué en premier, puis démarrez un autre processus.
Apprentissage recommandé : Tutoriel Golang
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!