golang实现文件监控
习惯使用iterm2终端打开2个屏,一个实时输出脚本运行的结果,一个使用vim编辑脚本测试,这样当vim编辑修改的时候左侧可以及时的看到执行结果,方便调试
实现思路
1.定时器,间隔1s读取文件并生成md5,和1s之前的md5对比,如果一致则文件没有改动,不一致则运行脚本,运行完之后当前md5赋值到上一次的md5对象 2.文件监控限制为常用的go/py文件
可拓展范围
后面可扩展为监听事件event变动(配置文件变动/数据库数据状态改变等等),回调每个event的callback函数去执行不同的逻辑
执行说明
1.当命令行传入的 -file 参数是一个.py文件时,调用os/exec模块,执行python3 **.py;-file 参数是一个.go文件时,执行 go run **.go 命令获取终端标准输出; 2.终端crontrol + C 退出时,检测到退出信号,接触程序 3.打包 go build 4.运行 ./gomonitor -file **.go
实现代码:
package main
import (
"flag"
"fmt"
"os"
"os/signal"
"syscall"
"io"
"io/ioutil"
"os/exec"
"time"
"strings"
"crypto/md5"
)
var Usage = `
go build
ls
./gomonitor -file /Users/chengxinyao/go/src/gojob/app/test.go
`
//检测的文件
var File = flag.String("file","", "检测的文件")
//上一次的md5
var PreMd5 string
//本次md5
var CurrentMd5 string
func GetMd5(str string) string {
w := md5.New()
io.WriteString(w, str)
md5str := fmt.Sprintf("%x", w.Sum(nil))
return md5str
}
func main(){
flag.Parse()
file := *File
signalCh := make(chan os.Signal)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
if strings.HasSuffix(file,".py") || strings.HasSuffix(file,".go"){
PreMd5 = "aaaa"//默认赋值 run函数会检测md5
//起一个定时器 监听文件 MD5变化 变化则自动调用RunCommand
t := time.NewTicker(1 * time.Second)
for {
select {
case <-t.C:
run(file)
case <- signalCh:
fmt.Println("kill ")
t.Stop()
return
}
}
}else{
fmt.Println("仅支持.go/.py文件监控")
}
}
func run(file string){
fileObj,_ := os.Open(file)
defer fileObj.Close()
data,_ := ioutil.ReadAll(fileObj)
CurrentMd5 = GetMd5(string(data))
command := "go"
args := make([]string,0)
if strings.HasSuffix(file,".py"){
command = "python3"
}else{
args = append(args,"run")
}
//上一次的md5 != 本次的md5 则执行
if PreMd5 != CurrentMd5{
args = append(args,file)
ExecuteCommand(command,args...)
PreMd5 = CurrentMd5
}
return
}
func ExecuteCommand(command string,args ...string) error {
cmd := exec.Command(command,args...)
stdout, err := cmd.StdoutPipe()
cmd.Stderr = cmd.Stdout
if err != nil {
return err
}
if err = cmd.Start(); err != nil {
return err
}
for {
tmp := make([]byte, 1024)
_, err := stdout.Read(tmp)
fmt.Print(string(tmp))
if err != nil {
break
}
}
if err = cmd.Wait(); err != nil {
return err
}
return nil
}
文章转载自codefan,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。