博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用crypto/ssh做的简单远程发布工具,scp,kill,start
阅读量:5919 次
发布时间:2019-06-19

本文共 7427 字,大约阅读时间需要 24 分钟。

  昨天项目组中的一个兄弟,问我我们远程发布是怎么做的,说现在他在维护好几个项目,每个项目需要部署的时候,要把编译好的文件拖过去,然后重启tomcat,本来很简单的事情,但是很浪费时间,问我有没有办法脚本化

  他自己的机器是windows的,scp命令可以通过安装解决,但是要远程关闭、开启tomcat,却不是脚本解决的事情,应该通过ssh解决,然后又需要放在其他机器上拿过去用,我就直接给提用golang实现了一个,代码如下:

 

package mainimport (	"bufio"	"flag"	"fmt"	"io"	"io/ioutil"	"log"	"net"	"os"	"path/filepath"	"strings"	"golang.org/x/crypto/ssh")var (	auth       string	publicKey  string	passwd     string	user       string	ip_port    string	dpath      string	spath      string	tomcatPath string	killName   string)func main() {	log.SetFlags(log.Lshortfile | log.Ltime | log.Ldate)	flag.Parse()	//read config file	myConfig := new(Config)	myConfig.InitConfig("./config.conf")	auth = myConfig.Read("test", "auth")	publicKey = myConfig.Read("test", "publicKey")	passwd = myConfig.Read("test", "passwd")	user = myConfig.Read("test", "user")	ip_port = myConfig.Read("test", "ip_port")	dpath = myConfig.Read("test", "dpath")	spath = myConfig.Read("test", "spath")	tomcatPath = myConfig.Read("test", "tomcatPath")	killName = myConfig.Read("test", "killName")	//目标文件	//	File, err := os.Open(spath)	//	if err != nil {	//		fmt.Println("打开文件失败:", err)	//		os.Exit(1)	//	}	//	info, _ := File.Stat()	//	defer File.Close()	var Client *ssh.Client	var err error	if strings.EqualFold(auth, "password") {		Client, err = dail(user, passwd, ip_port)	} else {		Client, err = dailPublic(user, publicKey, ip_port)	}	if err != nil {		fmt.Printf("连接%s失败.\n", err)	}	defer Client.Close()	//	scp(Client, File, info.Size(), dpath)	session, err := Client.NewSession()	defer session.Close()	if err != nil {		fmt.Println("创建Session失败:", err)		return	}	//遍历并复制	err = filepath.Walk(spath, func(path string, f os.FileInfo, err error) error {		if f == nil {			return err		}		if f.IsDir() {			newpath := strings.Replace(path, spath, dpath, len(spath))			dname := strings.Replace(newpath, "\\", "/", -1)			mkdir(Client, dname)			return nil		}		//不是路径的,就复制文件		File, err := os.Open(path)		if err != nil {			fmt.Println("打开文件失败:", err)			os.Exit(1)		}		info, _ := File.Stat()		defer File.Close()		newpath := strings.Replace(path, spath, dpath, len(spath))		dname := strings.Replace(newpath, "\\", "/", -1)		fmt.Printf("dname %s\n", dname)		scp(Client, File, info.Size(), dname)		return nil	})	//停止tomcat	kill(Client, killName)	//启动tomcat	start(Client, tomcatPath)}func scp(client *ssh.Client, File io.Reader, size int64, path string) {	filename := filepath.Base(path)	dirname := strings.Replace(filepath.Dir(path), "\\", "/", -1)	session, err := client.NewSession()	if err != nil {		fmt.Println("创建Session失败:", err)		return	}	go func() {		w, _ := session.StdinPipe()		fmt.Fprintln(w, "C0644", size, filename)		io.CopyN(w, File, size)		fmt.Fprint(w, "\x00")		w.Close()	}()	fmt.Println("dir name is %s", dirname)	if err := session.Run(fmt.Sprintf("/usr/bin/scp -qrt %s/", dirname)); err != nil {		fmt.Println("执行scp命令失败:", err)		if err != nil {			session.Close()			return		}	} else {		fmt.Printf("%s 发送成功.\n")		session.Close()	}	if session, err = client.NewSession(); err == nil {		defer session.Close()		buf, err := session.Output(fmt.Sprintf("/usr/bin/md5sum %s", path))		if err != nil {			fmt.Println("检查md5失败:", err)			return		}		fmt.Printf("MD5:\n%s\n", string(buf))	}}func mkdir(client *ssh.Client, path string) {	fmt.Printf("create path %s\n", path)	session, err := client.NewSession()	if err != nil {		fmt.Println("创建Session失败:", err)		return	}	session.Run(fmt.Sprintf("[ ! -d %s ] && mkdir %s", path, path))	defer session.Close()}func kill(client *ssh.Client, path string) {	fmt.Printf("kill tomcat path is %s\n", path)	session, err := client.NewSession()	if err != nil {		fmt.Println("创建Session失败:", err)		return	}	session.Run(fmt.Sprintf("kill -9 `ps -ef|grep %s|grep -v 'grep'|awk '{print $2}'`", path))	defer session.Close()}func start(client *ssh.Client, path string) {	fmt.Printf("start tomcat path is %s\n", path)	session, err := client.NewSession()	if err != nil {		fmt.Println("创建Session失败:", err)		return	}	mt := fmt.Sprintf("source /etc/profile && %s/startup.sh", path)	fmt.Println(mt)	session.Stdout = os.Stdout	session.Stderr = os.Stderr	err = session.Run(mt)	if err != nil {		fmt.Println(err)	}	defer session.Close()}func dail(user, password, ip_port string) (*ssh.Client, error) {	PassWd := []ssh.AuthMethod{ssh.Password(password)}	Conf := ssh.ClientConfig{User: user, Auth: PassWd, HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {		return nil	},	}	return ssh.Dial("tcp", ip_port, &Conf)}func dailPublic(user, publicKey, ip_port string) (*ssh.Client, error) {	if strings.HasSuffix(publicKey, ".pub") {		publicKey = strings.TrimSuffix(publicKey, ".pub")	}	signer, err := readPrivateKey(publicKey)	if err != nil {		fmt.Println(err)	}	PassWd := []ssh.AuthMethod{ssh.PublicKeys(signer)}	Conf := ssh.ClientConfig{User: user, Auth: PassWd, HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {		return nil	},	}	return ssh.Dial("tcp", ip_port, &Conf)}func readPrivateKey(path string) (ssh.Signer, error) {	f, err := os.Open(path)	if err != nil {		return nil, err	}	defer f.Close()	b, err := ioutil.ReadAll(f)	if err != nil {		return nil, err	}	return ssh.ParsePrivateKey(b)}//配置type Config struct {	Mymap  map[string]string	strcet string}func (c *Config) InitConfig(path string) {	c.Mymap = make(map[string]string)	f, err := os.Open(path)	if err != nil {		panic(err)	}	defer f.Close()	r := bufio.NewReader(f)	for {		b, _, err := r.ReadLine()		if err != nil {			if err == io.EOF {				break			}			panic(err)		}		s := strings.TrimSpace(string(b))		//fmt.Println(s)		if strings.Index(s, "#") == 0 {			continue		}		n1 := strings.Index(s, "[")		n2 := strings.LastIndex(s, "]")		if n1 > -1 && n2 > -1 && n2 > n1+1 {			c.strcet = strings.TrimSpace(s[n1+1 : n2])			continue		}		if len(c.strcet) == 0 {			continue		}		index := strings.Index(s, "=")		if index < 0 {			continue		}		frist := strings.TrimSpace(s[:index])		if len(frist) == 0 {			continue		}		second := strings.TrimSpace(s[index+1:])		pos := strings.Index(second, "\t#")		if pos > -1 {			second = second[0:pos]		}		pos = strings.Index(second, " #")		if pos > -1 {			second = second[0:pos]		}		pos = strings.Index(second, "\t//")		if pos > -1 {			second = second[0:pos]		}		pos = strings.Index(second, " //")		if pos > -1 {			second = second[0:pos]		}		if len(second) == 0 {			continue		}		key := c.strcet + "." + frist		c.Mymap[key] = strings.TrimSpace(second)	}}func (c Config) Read(node, key string) string {	key = node + "." + key	v, found := c.Mymap[key]	if !found {		return ""	}	return v}

  

使用配置文件指定参数:

[test]auth = key                #password or key,现在只做了password和rsa公钥publicKey = C:\Users\issuser\Desktop\key\id_rsapasswd  = xxxxuser    = xxxxip_port = xx.xx.xx.xx:22dpath   =  /work/ovuems/dapingAgent/webapps/dapingAgent/WEB-INF/classes/com    #目标路径spath   =      D:\ideaSpace\dapingAgent\target\classes\com    #本地路径killName = /work/ovuems/dapingAgent/bin                 #和下面的tomcat路径一致,防止需要杀掉多个进程的时候,用于灵活处理tomcatPath = /work/ovuems/dapingAgent/bin      #tomcat路径,到bin这一级

 

说明:

该项目只做了4件事

1、连接ssh

2、复制本地编译好的class文件到远端(递归方式)

3、kill掉tomcat

4、启动tomcat

 

发现问题,启动tomcat的时候,启动不了,打印出来的消息为:

Neither the JAVA_HOME nor the JRE_HOME environment variable is defined At least one of these environment variable is needed to run this program

但是在机器上面查找,发现环境变量已经配置,没有办法,执行之前加上了 source /etc/profile予以解决

 

 

转载于:https://www.cnblogs.com/wency/p/9511418.html

你可能感兴趣的文章
根据Request ID找到对应的Session信息
查看>>
应用服务器性能优化 之 消息队列(MQ:Message Queue)
查看>>
npm模块安装机制
查看>>
Sunisoft.IrisSkin.SkinEngine 设置winform皮肤
查看>>
RMAN-06172 Troubleshooting
查看>>
html5——canvas画布
查看>>
BZOJ1058: [ZJOI2007]报表统计(set)
查看>>
Spark 核心概念RDD
查看>>
从PRISM开始学WPF(一)WPF?
查看>>
【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类
查看>>
看了这个教程,学会快速找出三等分点
查看>>
以太坊钱包Geth使用命令
查看>>
nginx配置
查看>>
Redis配置不当致使root被提权漏洞
查看>>
ubutu14.04无法使用sudo,也无法切换到root用户去解决问题怎么办?
查看>>
使用 NuGet 管理项目库
查看>>
004-Maven的安装与配置
查看>>
C# 插入、删除Excel分页符
查看>>
RTMP、RTSP、HTTP视频协议详解(附:直播流地址、播放软件)
查看>>
laravel构造函数和中间件执行顺序问题
查看>>