大佬教程收集整理的这篇文章主要介绍了分享一个小东西,自动到指定的地方下载动态版本的命令,然后根据配置循环执行调用.,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
写此小程序的原因是,研究小米的open-falcon的时候用他们的插件管理感觉不适合我们公司,就自动动手写了个基于服务端的版本控制的,命令下载时基于http的所以也比较方便.
先发下执行的结果:
开始解析cfg.json配置文件.解析配置文件成功: {gyc D:/code/20151117/src/ssh true 27.0.0.1:2789 http://127.0.0.1:1789/pkg/ :1789 true 60} 开始初始化本地命令... 初始化本地命令完成... [{Client.go D:\code\20151117\src\ssh\client.go 256034f7168a3937b124ad89227f0ea9 {sshd D:\code\20151117\src\ssh\sshd af7ec72582c33ecd97dc5abf0e747e92}] D:/code/20151117/src/ssh 2015-11-18 17:46:29获取服务端版本! {fmt.exe fe117de8dbf1a460e66d2a799bde17cf 30 } 2015-11-18 17:46:29开始验证本地! {Test01.exe e6a54c6f478d93828cb635e97d710ba6 30 } 2015-11-18 17:46:29开始验证本地! 开始下载:http://127.0.0.1:1789/pkg/fmt.exe 开始下载:http://127.0.0.1:1789/pkg/Test01.exe tmp/Test01.exe D:/code/20151117/src/ssh/Test01.exe tmp/fmt.exe D:/code/20151117/src/ssh/fmt.exe 2015-11-18 17:46:29 开始执行Test01.exe 2015-11-18 17:46:29 开始执行fmt.exe 命令Test01.exe结果:This is Test01 命令fmt.exe结果:2015-11-18 17:46:29.3219182 +0800 CST 命令Test01.exe结果:This is Test01 命令fmt.exe结果:2015-11-18 17:46:59.3536359 +0800 CST 2015-11-18 17:47:29获取服务端版本! 清除过期的命令:Test01.exe. {fmt.exe fe117de8dbf1a460e66d2a799bde17cf 30 } 2015-11-18 17:47:29 退出执行Test01.exe 命令fmt.exe结果:2015-11-18 17:47:29.3933541 +0800 CST
废话不多说直接上源码:
服务端简单的代码小例子:
server.go
package main import ( "encoding/json" "fmt" "net" ) type versionInfo struct { Name String `json:name` Md5 String `json:md5` Interval int `json:interval` Args String `json:args` } //测试代码.服务端可以自己按需求定义. func main() { var list []versionInfo list = []versionInfo{{"fmt.exe","fe117de8dbf1a460e66d2a799bde17cf",30,""},{"Test01.exe","e6a54c6f478d93828cb635e97d710ba6",""}} //这些内容命令版本多的时候可以用数据库来控制,不多就随便自己搞搞吧,b,err := json.Marshal(list) if err != nil { fmt.Printf("初始话数据失败:%s\n",err) return } lis,err := net.Listen("tcp",":2789") if err != nil { fmt.Printf("初始化服务端失败:%s\n",err) return } defer lis.Close() for { con,err := lis.Accept() if err != nil { fmt.Println(err) conTinue } go func(con net.Conn) { defer con.Close() buf := make([]byte,512) n,err := con.Read(buf) if err != nil { fmt.Println(err) return } if String(buf[:n]) != "gyc" { //这里的值需要根据自己来控制,比如每次收到的请求到数据库@L_674_16@来取版本返回. con.Write([]byte("No this group!")) return } con.Write(b) }(con) } }
我得用目录是:new
getServerVersion.go
package new import ( "encoding/json" "fmt" "io/IoUtil" "net" "os" "time" ) func GetVersion(group String) []RemoteVersionInfo { var list []RemoteVersionInfo This: con,err := net.Dial("tcp",Getconfig().GetVersionServer) if err != nil { fmt.Printf("%s 从%s获取命令版本信息错误: %s\n",GetNowTime(),Getconfig().GetVersionServer,err) time.Sleep(60e9) goto This } defer con.Close() _,err = con.Write([]byte(group)) if err != nil { fmt.Printf("发送%s的version请求失败:%s\n",group,err) time.Sleep(60e9) goto This } buf,err := IoUtil.ReadAll(con) if err != nil { fmt.Printf("%s 获取命令版本信息错误: %s\n",err) time.Sleep(60e9) goto This } if String(buf) == "No this group!" { fmt.Printf("版本库找不到此分组:%s\n",group) os.Exit(1) } err = json.Unmarshal(buf,&list) if err != nil { fmt.Printf("%s 解析获取的版本消息错误: %s\n",err) time.Sleep(60e9) goto This } return list }init_var.go
package new import ( "encoding/json" "fmt" "io/IoUtil" "os" "path/filepath" "Strings" "sync" ) var CmdPath String var config ConfigJson var Lock *sync.RWMutex = new(sync.RWMuteX) var CmdFuncMap *FuncMap func Getconfig() *ConfigJson { Lock.RLock() defer Lock.RUnlock() return &config } func init() { err := parseConfig("cfg.json") if err != nil { os.Exit(1) } info,err := os.Lstat(Getconfig().CmdDirPath) CmdPath = Getconfig().CmdDirPath if err != nil || !info.IsDir() { fmt.Printf("校验目录失败: %s \n",err) err := initDir() if err != nil { os.Exit(1) } fmt.Printf("使用默认配置做根目录: %s\n",CmdPath) } initBaseCmdInfo(CmdPath) CmdFuncMap = &FuncMap{make(map[String]*ExecCmdInfo),new(sync.RWMuteX)} } func parseConfig(configPath String) error { fmt.Printf("开始解析%s配置文件.",configPath) b,err := IoUtil.ReadFile(configPath) if err != nil { fmt.Printf("读取配置文件出错: %s\n",err) return err } err = json.Unmarshal(b,&config) if err != nil { fmt.Printf("解析配置出错: %s\n",err) return err } fmt.Println("解析配置文件成功: ",config) return nil } func initDir() error { fmt.Println("初始化默认路径.") p,err := os.Getwd() if err != nil { fmt.Printf("获取当前目录错误: %s\n",err) return err } info,err := os.Lstat("cmd") if err == nil && info.IsDir() { CmdPath = Strings.replace(p,`\`,`/`,20) + `/cmd` return nil } err = os.Mkdir("cmd",0644) if err != nil { fmt.Printf("初始化文件夹失败: %s\n",err) return err } CmdPath = Strings.replace(p,20) + `/cmd` return nil } func initBaseCmdInfo(path String) { fmt.Println("开始初始化本地命令...") err := filepath.Walk(path,run) if err != nil { fmt.Printf("%s 初始化命令列表出错: %s",err) os.Exit(1) } fmt.Println("初始化本地命令完成...") }run.go
package new import ( "fmt" "os/exec" "Strings" "time" ) func R() { if Getconfig().Debug { fmt.Printf("%s获取服务端版本!\n",GetNowTime()) } list := GetVersion(Getconfig().Group) CmdFuncMap.Lock.Lock() for k,m := range CmdFuncMap.Map { if !Contain(k,list) { fmt.Printf("清除过期的命令:%s.\n",k) m.Exit <- true delete(CmdFuncMap.Map,k) } } CmdFuncMap.Lock.Unlock() for _,cmdVersion := range list { fmt.Println(cmdVersion) CmdFuncMap.Lock.RLock() k,ok := CmdFuncMap.Map[cmdVersion.Name] CmdFuncMap.Lock.RUnlock() if ok { if k.M5 == cmdVersion.Md5 { conTinue } loadcmdbaseinfo := LoadCmdBaseInfo{k.Name,k.Path,k.M5} go update(loadcmdbaseinfo,cmdVersion) conTinue } cmd := index(cmdVersion) if cmd != nil { CmdFuncMap.Lock.Lock() CmdFuncMap.Map[cmd.Name] = cmd go cmd.Run() CmdFuncMap.Lock.Unlock() } } } func index(r RemoteVersionInfo) *ExecCmdInfo { if Getconfig().Debug { fmt.Printf("%s开始验证本地!\n",GetNowTime()) } var g chan bool = make(chan bool,1) for _,v := range LocalCmdList { if v.Name == r.Name && v.Md5 == r.Md5 { return &ExecCmdInfo{r.Name,v.Path,r.Md5,r.Interval,split(r.Args),g} } } v := LoadCmdBaseInfo{r.Name,fmt.Sprintf("%s/%s",CmdPath,r.Name),r.Md5} go update(v,r) return nil } func update(v LoadCmdBaseInfo,r RemoteVersionInfo) { var url String = Getconfig().GetCmdAddr if !Strings.HasSuffix(url,"/") { url = url + "/" } url = url + r.Name str := Download(r.Name,url) if str != Strings.ToLower(r.Md5) { return } CmdFuncMap.Lock.Lock() defer CmdFuncMap.Lock.Unlock() k,ok := CmdFuncMap.Map[r.Name] if ok { k.Exit <- true time.Sleep(1e9) } if !MoveFile(fmt.Sprintf("%s/%s","tmp",v.Path) { return } var g chan bool = make(chan bool,1) E := &ExecCmdInfo{r.Name,g} CmdFuncMap.Map[r.Name] = E go E.Run() } func (this *ExecCmdInfo) Run() { fmt.Printf("%s 开始执行%s\n",this.Name) var exit bool = false go func() { b := <-this.Exit if b { exit = b } }() for { if exit { break } cmd := exec.Command(this.Path,this.Args...) //err := cmd.Run() b,err := cmd.output() if err != nil { fmt.Printf("执行%s出错:%s\n",this.Name,err) } if Getconfig().Debug { fmt.Printf("命令%s结果:%s",String(b)) } time.Sleep(time.Second * time.Duration(this.Interval)) } fmt.Printf("%s 退出执行%s\n",this.Name) }
package new import "sync" type ConfigJson struct { Group String `json:group` CmdDirPath String `json:cmddirpath` Autoupdate bool `json:autoupdate` GetVersionServer String `json:vetversionserver` GetCmdAddr String `json:getcmdaddr` Listen String `json:listen` Debug bool `json:debug` update int `json:update` } type RemoteVersionInfo struct { Name String `json:name` Md5 String `json:md5` Interval int `json:interval` Args String `json:args` } type ExecCmdInfo struct { Name String Path String M5 String Interval int Args []String Exit chan bool } type LoadCmdBaseInfo struct { Name String Path String Md5 String } type FuncMap struct { Map map[String]*ExecCmdInfo Lock *sync.RWMutex }
package new import ( "crypto/md5" "fmt" "io" "net/http" "os" "Strings" "time" ) var LocalCmdList []LoadCmdBaseInfo func run(path String,info os.FileInfo,err error) error { if err != nil { return err } if info.IsDir() { return nil } m5 := Md5(path) if m5 != "" { LocalCmdList = append(LocalCmdList,LoadCmdBaseInfo{info.Name(),path,m5}) } return nil } func Md5(path String) String { File,err := os.Open(path) if err != nil { fmt.Printf("%s 校验%s的md5出错:%s\n",err) return "" } M := md5.New() io.Copy(M,FilE) b := m.Sum([]byte{}) return fmt.Sprintf("%x",b) } func GetNowTime() String { return time.Now().Format("2006-01-02 15:04:05") } func Download(name,url String) String { resp,err := http.Get(url) fmt.Printf("开始下载:%s\n",url) if err != nil || resp.StatusCode != 200 { fmt.Printf("%s 下载%s出错: %s\n",url,err) return "" } os.Mkdir("tmp",0644) defer resp.body.Close() name = "tmp/" + name File,err := os.Create(Name) if err != nil { fmt.Printf("%s 创建文件%s错误: %s\n",name,err) return "" } io.Copy(File,resp.body) File.Close() return Md5(Name) } func split(str String) []String { var l []String list := Strings.Split(str," ") for _,v := range list { if len(v) == 0 { conTinue } if Strings.Contains(v," ") { list := Strings.Split(v," ") for _,v := range list { if len(v) == 0 { conTinue } l = append(l,v) } conTinue } l = append(l,v) } return l } func MoveFile(s,d String) bool { fmt.Println(s,d) sFile,err := os.Open(s) if err != nil { fmt.Printf("移动文件%s出错:%s\n",s,err) return false } defer sFile.Close() dFile,err := os.Create(d) if err != nil { fmt.Printf(" 新建文件%s出错:%s\n",err) return false } defer dFile.Close() io.Copy(dFile,sFilE) return true } func Contain(k String,list []RemoteVersionInfo) bool { for _,v := range list { if k == v.Name { return true } } return false }
package main import ( "fmt" "new" "time" ) func main() { j := new.Getconfig() go func() { for { new.R() time.Sleep(time.Second * time.Duration(j.updatE)) } }() SELEct {} }下面是:实例的配置文件:cfg.json
{"Group":"gyc",
"CmdDirPath":"D:/code/201508221",
"Autoupdate":true,
"GetVersionServer":"127.0.0.1:2789",
"GetCmdAddr":"http://127.0.0.1:1789/pkg/",
"Listen":":1789",
"Debug":true,
"update":60}
以上是大佬教程为你收集整理的分享一个小东西,自动到指定的地方下载动态版本的命令,然后根据配置循环执行调用.全部内容,希望文章能够帮你解决分享一个小东西,自动到指定的地方下载动态版本的命令,然后根据配置循环执行调用.所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。