In Golang können Sie fsnotify verwenden, um die Dateiüberwachung zu implementieren. fsnotify ist ein plattformübergreifendes Dateisystemüberwachungstool in der Go-Sprache, das eine kanalbasierte, plattformübergreifende Echtzeitüberwachungsschnittstelle implementiert. Golang kann Dateien über fsnotify überwachen und das Programm durch Dateiänderungen neu starten.
Die Betriebsumgebung dieses Tutorials: Windows 10-System, GO Version 1.18, Dell G3-Computer.
In Golang können Sie fsnotify verwenden, um die Dateiüberwachung zu implementieren.
golang überwacht Dateien über fsnotify und startet das Programm bei Dateiänderungen neu.
Plattformübergreifendes Dateisystem-Überwachungstool der Go-Sprache – fsnotify
Im Linux-Kernel ist Inotify ein Mechanismus, der verwendet wird, um User-Space-Programme über Dateisystemänderungen zu benachrichtigen. Es überwacht Dateisystemänderungen wie das Erstellen, Ändern, Löschen usw. von Dateien und kann Anwendungen über entsprechende Ereignisse benachrichtigen.
Inotify kann sowohl Dateien als auch Verzeichnisse überwachen. Bei der Überwachung eines Verzeichnisses können das Verzeichnis und jedes Unterverzeichnis und jede Datei im Verzeichnis gleichzeitig überwacht werden. Der Standardbibliotheks-Systemaufruf von Golang implementiert diesen Mechanismus.
Zur weiteren Erweiterung und Abstraktion implementiert das Paket github.com/fsnotify/fsnotify eine kanalbasierte, plattformübergreifende Echtzeit-Überwachungsschnittstelle.
Verwendung des fsnotify-Tools
1. Laden Sie die benötigten Pakete herunter
go get github.com/fsnotify/fsnotify
Nach dem Login kopieren
2. Verwenden Sie fsnotify, um Dateien zu überwachen
1
2
3 4
5
6 19
20
21
22 . 23.
24.
25.
26.
27.
28.
29 3 5363738 39 51 52
53
54
55 56
57
58
59
60
package main;
import (
"github.com/fsnotify/fsnotify" code><p class="line number37 index36 alt2"></p>
<code class="js leerzeichen"> "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 {};
}
|
Die Testergebnisse lauten wie folgt:
Alle unsere Vorgänge im tmp-Verzeichnis wurden erfasst, aber es gibt ein Problem mit fsnotify. Es kann uns nicht dabei helfen, die Vorgangsereignisse von Unterverzeichnissen und Enkelverzeichnissen rekursiv zu erfassen von uns selbst umgesetzt.
Ein weiteres Problem besteht darin, dass, wenn wir den Ordnernamen ändern, der event.Name in fsnotify immer noch der ursprüngliche Dateiname ist, was erfordert, dass wir zuerst die vorherige Überwachung entfernen und dann eine neue Überwachung im Umbenennungsereignis hinzufügen.
Geändert wie folgt:
1
2
3
4
5
6
7
8
9
10
11
12
13 . 14.
15.
16.
17.
18 2 6272829 30 42 43
44
45
46 47 59 60616263 64 7 6777879 80 8182838485868788
Code>
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 {};
}
|
Die Testergebnisse lauten wie folgt:
Nach dem obigen Beispiel verwenden wir fsnotify, um eine Überwachungskonfigurationsdatei zu schreiben. Wenn die Konfigurationsdatei geändert wird, wird der Dienst neu gestartet.
Wir schreiben zunächst ein exe-Programm, das ausgeführt werden kann. Der server.go-Code lautet wie folgt:
1
2
3
4
5
6
7
8 9. 10
21 22
23
24
25.
26.
27.
28.
29.
30.
31.
32.
33 37
38
39
40
41 4243 54
5 5
56
57
58
package main;
import (
"io/ioutil"
code>"log"
"encoding/json"
"net"
"fmt"
"os"
"os/signal"
)
const (
confFilePath = ./conf/conf.json" ;
) code><p class="line number49 index48 alt2"></p>
<code class="js rooms">
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文件
Der Code der Überwachungsdatei fsnotify3.go lautet wie folgt:
1
2
3
4
5
6
7
8
9 10
11 12 24 252627 28 52
53
54
55
56
57 58
59
60
61
62 8
69
70
71
72
73 8586878889 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" );
}
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" ); 🎜
} 🎜
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 {};
}
|
Wir führen die Datei fsnotify3.go aus, um unsere Konfigurationsdatei zu überwachen
Wie Sie auf dem Bild oben sehen können, wird der Vorgang ausgeführt, wenn wir die Portnummer in der Konfigurationsdatei ändern Zuerst getötet und dann einen anderen Prozess gestartet.
Empfohlenes Lernen: Golang-Tutorial
Das obige ist der detaillierte Inhalt vonSo implementieren Sie die Dateiüberwachung in Golang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!