暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

golang实现文件监控

codefan 2021-03-23
1343

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([]byte1024)
  _, 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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论