分享一个小东西,自动到指定的地方下载动态版本的命令,然后根据配置循环执行调用.

分享一个小东西,自动到指定的地方下载动态版本的命令,然后根据配置循环执行调用.,第1张

概述写此小程序的原因是,研究小米的open-falcon的时候用他们的插件管理感觉不适合我们公司,就自动动手写了个基于服务端的版本控制的,命令下载时基于http的所以也比较方便. 代码写的比较紧急有点乱,先这样吧,回头用起来再调优一下. 先发下执行的结果: 开始解析cfg.json配置文件.解析配置文件成功: {gyc D:/code/20151117/src/ssh true27.0.0.1:2

写此小程序的原因是,研究小米的open-falcon的时候用他们的插件管理感觉不适合我们公司,就自动动手写了个基于服务端的版本控制的,命令下载时基于http的所以也比较方便.

代码写的比较紧急有点乱,先这样吧,回头用起来再调优一下.

先发下执行的结果:

开始解析cfg.Json配置文件.解析配置文件成功:  {gyc D:/code/20151117/src/ssh true27.0.0.1:2789 http://127.0.0.1:1789/pkg/ :1789 true 60}开始初始化本地命令...初始化本地命令完成...[{clIEnt.go D:\code151117\src\ssh\clIEnt.go 256034f7168a3937b124ad89227f0ea9 {sshd D:\code151117\src\ssh\sshd af7ec72582c33ecd97dc5abf0e747e92}]D:/code/20151117/src/ssh2015-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.exetmp/Test01.exe D:/code/20151117/src/ssh/Test01.exetmp/fmt.exe D:/code/20151117/src/ssh/fmt.exe2015-11-18 17:46:29 开始执行Test01.exe2015-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 CST2015-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 mainimport (	"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" { //这里的值需要根据自己来控制,比如每次收到的请求到数据库查询来取版本返回.				con.Write([]byte("No this group!"))				return			}			con.Write(b)		}(con)	}}

下面是每个实例的代码.

我得用目录是:new

getServerVersion.go

package newimport (	"enCoding/Json"	"fmt"	"io/IoUtil"	"net"	"os"	"time")func GetVersion(group string) []RemoteVersionInfo {	var List []RemoteVersionInfoThis:	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 newimport (	"enCoding/Json"	"fmt"	"io/IoUtil"	"os"	"path/filepath"	"strings"	"sync")var Cmdpath stringvar config ConfigJsonvar Lock *sync.RWMutex = new(sync.RWMutex)var CmdFuncMap *FuncMapfunc 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 newimport (	"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)}


type.go
package newimport "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}

usefunc.go
package newimport (	"crypto/md5"	"fmt"	"io"	"net/http"	"os"	"strings"	"time")var LocalCmdList []LoadCmdBaseInfofunc 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}


下面是入口函数:

main.go

package mainimport (	"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}
总结

以上是内存溢出为你收集整理的分享一个小东西,自动到指定的地方下载动态版本的命令,然后根据配置循环执行调用.全部内容,希望文章能够帮你解决分享一个小东西,自动到指定的地方下载动态版本的命令,然后根据配置循环执行调用.所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1286068.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存