go监视文件改变实现同步--包含遍历文件夹,执行cmd命令,检测文件改变
package main
import (
"fmt"
"time"
"os/exec"
"strings"
"io/ioutil"
"os"
"github.com/howeyc/fsnotify"
"sync"
)
const (
filePath = "/home/ubuntu/GzhuOJ/public"
hostname = "root@gzhuacm.cn"
remotePath = "/home/public"
)
var watcher *fsnotify.Watcher
var mutex sync.Mutex
func Print(args ...interface{}) {
fmt.Println(time.Now(), args)
}
func isDir(path string) bool {
fileInfo, err := os.Stat(path)
if err != nil {
Print("error:", err.Error())
return false
}
return fileInfo.IsDir()
}
func watchPath(filePath string) {
Print("watchPath:", filePath)
err := watcher.Watch(filePath)
if err != nil {
Print(err.Error())
return
}
}
func broweDir(path string) {
Print("broweDir:", path)
dir, err := os.Open(path)
if err != nil {
Print("error:", err.Error())
return
}
defer dir.Close()
names, err := dir.Readdirnames(-1)
if err != nil {
Print("error:", err.Error())
return
}
for _, name := range names {
dirPath := path + "/" + name
if !isDir(dirPath) {
continue
}
watchPath(dirPath)
broweDir(dirPath)
}
}
func main() {
var err error
watcher, err = fsnotify.NewWatcher()
if err != nil {
panic(err)
}
defer watcher.Close()
broweDir(filePath)
watchPath(filePath)
dealWatch()
}
func copy(event *fsnotify.FileEvent) *exec.Cmd {
return exec.Command(
"scp",
"-r",
"-P 23456",
event.Name,
hostname+":"+remotePath+strings.TrimPrefix(event.Name, filePath))
}
func remove(event *fsnotify.FileEvent) *exec.Cmd {
return exec.Command(
"ssh",
"-p 23456",
hostname,
`rm -r `+remotePath+strings.TrimPrefix(event.Name, filePath)+``)
}
func dealWatch() {
for {
func() {
//mutex.Lock()
//defer mutex.Unlock()
select {
case event := <-watcher.Event:
Print("event: ", event)
var cmd *exec.Cmd
if event.IsCreate() || event.IsModify() {
cmd = copy(event)
}
if event.IsDelete() || event.IsRename() {
cmd = remove(event)
}
Print("cmd:", cmd.Args)
stderr, err := cmd.StderrPipe()
if err != nil {
Print(err.Error())
return
}
defer stderr.Close()
stdout, err := cmd.StdoutPipe()
if err != nil {
Print(err.Error())
return
}
defer stdout.Close()
if err = cmd.Start(); err != nil {
Print(err.Error())
return
}
errBytes, err := ioutil.ReadAll(stderr)
if err != nil {
Print(err.Error())
return
}
outBytes, err := ioutil.ReadAll(stdout)
if err != nil {
Print(err.Error())
return
}
if len(errBytes) != 0 {
Print("errors:", string(errBytes))
}
if len(outBytes) != 0 {
Print("output:", string(outBytes))
}
if err = cmd.Wait(); err != nil {
Print(err.Error())
}
case err := <-watcher.Error:
Print("error: ", err.Error())
}
}()
}
}
go cmd 的命令里不能ssh user@ip "rm /home/public" 最后的参数”/home/public"不要写引号("),不然会执行命令失败,但命令行里不加引号可以执行,所以尽量不要加引号
要注意的是一个fsnotify.Watcher能watch多个文件和文件夹,不要一个Watcher watch一个文件夹或文件,太多会报Too many open files

浙公网安备 33010602011771号