• 强化go get命令


    强化go get命令

    • 利用ssh包,编写一个再window上类试运行go get的命令,将项目同时拉取到远程服务器的小项目

    • 大概思路
      • 读取配置文件,获取能够连接远程服务器的配置信息
      • 创建远程服务器的session
      • 解析命令,通过不同的信息,拉取不同的包
    • 源代码

    // conf.go
    package main
    
    
    import (
    	"log"
    	"os"
    	"path/filepath"
    	"gopkg.in/gcfg.v1"
    	valid "github.com/asaskevich/govalidator"
    )
    
    // Config 配置信息
    type Config struct{
    	// Servers 多台服务器
    	Servers map[string]*Server
    }
    
    // Server 服务器
    type Server struct{
    	User string
    	Port int
    	Host string
    	Password string
    	GoAbPath string    // (利用which go 执行golang命令绝对路径获取)
    }
    
    var (
    	// Conf 全局配置变量
    	Conf = new(Config)
    	// HomePath 项目位置
    	HomePath string 
    )
    
    func init(){
    	log.SetFlags(log.Ldate | log.Lshortfile)
    	var err error
    	HomePath,err = filepath.Abs(filepath.Dir(os.Args[0]))
    	if err!=nil{
    		log.Fatal(err)
    	}
    }
    
    // ReadConf 读取配置文件 
    func ReadConf(){
    
    	confPath := HomePath + "/conf.ini"
    
    	err := gcfg.ReadFileInto(Conf,confPath)
    	if err!=nil{
    		log.Fatal(err)
    	}
    
    	if Conf == nil {
    		log.Fatal("conf is nil")
    	}
    
    	for _,value := range Conf.Servers{
    		if !valid.IsIPv4(value.Host){
    			log.Fatal("请输入正确的IPv4类地址,错误的IP地址:",value.Host)
    		}
    	}
    
    }
    
    
    
    // main
    package main
    
    import (
    	"flag"
    	"fmt"
    	"io/ioutil"
    	"log"
    	"net"
    	"os"
    
    	// "os"
    	"os/exec"
    	"sync"
    	"time"
    
    	"golang.org/x/crypto/ssh"
    )
    
    // 设计思路
    // 多台服务器同时go get 包,保证多台服务器上有go,并且能够翻墙
    
    // SHost session and host
    type SHost struct {
    	Session  *ssh.Session
    	Host     string
    	GoAbPath string
    }
    
    // flagGit 命令
    var flagGit = flag.String("goget", "", "completely package go get,example goget github.com/gpmgo/gopm")
    
    // sessions 对话组
    var sHosts = make([]*SHost, 0)
    
    // wg 线程组
    var wg sync.WaitGroup
    
    func init() {
    	// 读取配置文件
    	ReadConf()
    	// 创建对话组
    	for _, value := range Conf.Servers {
    		sHost, err := Connect(value)
    		if err != nil {
    			log.Println(err)
    			return
    		}
    		sHosts = append(sHosts, sHost)
    	}
    }
    
    // Connect 创建服务器连接
    func Connect(server *Server) (*SHost, error) {
    
    	if server == nil {
    		err := fmt.Errorf("server is nil")
    		log.Println(err)
    		return nil, nil
    	}
    
    	// get auth method
    	auth := make([]ssh.AuthMethod, 0)
    	auth = append(auth, ssh.Password(server.Password))
    
    	clientConfig := &ssh.ClientConfig{
    		User:    server.User,
    		Auth:    auth,
    		Timeout: 30 * time.Second, // 连接超时时间
    		// 验证服务器的主机密钥 HostKeyCallback:ssh.InsecureIgnoreHostKey(),也可以
    		HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
    			return nil
    		},
    	}
    
    	addr := fmt.Sprintf("%s:%d", server.Host, server.Port)
    
    	client, err := ssh.Dial("tcp", addr, clientConfig)
    	if err != nil {
    		log.Println(err)
    		return nil, err
    	}
    
    	session, err := client.NewSession()
    	if err != nil {
    		log.Println(err)
    		return nil, err
    	}
    
    	return &SHost{Session: session, Host: server.Host, GoAbPath: server.GoAbPath}, nil
    }
    
    func main() {
    
    	flag.Parse()
    	switch *flagGit {
    	case "-h":
    		fmt.Println("completely package go get,example goget github.com/gpmgo/gopm")
    		return
    	case "":
    		return
    	default:
    		// 是否已经错误
    		var isErr bool
    		// 先在本机下载
    		cmd := exec.Command("cmd", "/C", "go get "+*flagGit)
    		log.Println(cmd.Args)
    		stdout, err := cmd.StdoutPipe()
    		if err != nil {
    			log.Println(err)
    		}
    		stderr, err := cmd.StderrPipe()
    		if err != nil {
    			log.Println(err)
    			isErr = true
    		}
    		if err := cmd.Start(); err != nil {
    			log.Println(err)
    			isErr = true
    		}
    		outBytes, err := ioutil.ReadAll(stdout)
    		if err != nil {
    			log.Println(err)
    			isErr = true
    		} else {
    			log.Println(string(outBytes))
    		}
    		errBytes, err := ioutil.ReadAll(stderr)
    		if err != nil {
    			log.Println(err)
    			isErr = true
    		} else {
    			log.Println(string(errBytes))
    		}
    		// 后再服务器上运行
    		for i := 0; i < len(sHosts); i++ {
    			sHosts[i].Session.Stderr = os.Stderr
    			sHosts[i].Session.Stdout = os.Stdout
    			Shell := fmt.Sprintf(" get -u %s", *flagGit)
    			log.Println(Shell)
    			err = sHosts[i].Session.Run("sudo " + sHosts[i].GoAbPath + Shell)
    			if err != nil {
    				log.Println(err, "出现错误的服务器的IP地址", sHosts[i].Host)
    				isErr = true
    			}
    		}
    		if isErr {
    			log.Println("拉取失败")
    		}
    	}
    }
    
    
    ;配置文件写入方法 利用配置文件的分组规则写
    [servers "A"]
    
    User = 用户名
    
    port = 开放端口号
    
    host = ip
    
    password = 密码
    
    goAbPath = /usr/local/go/bin/go
    
    • 曾经遇到的问题
      • go get 下来发现gopath路径下的src文件,没有拉取下来的文件,因为我开了module,即set GO111MODULE=on。所以来下来的代码放到gopath路径下的pkg文件夹下
      • 远程调用go命令的时候,他会说不具备go命令。但是自己远程服务器下是有配置的。最后只能通过利用which go获取go命令的绝对路径,进行运行。
  • 相关阅读:
    近期需要学习的
    sdfsdf
    思路绝对清楚,手段绝对下流【转】
    一宅镇京华——看谁还敢在我面前吹丫有钱 
    白天求生存,晚上求发展
    Ten Places to Go for SharePoint Development Information
    Life Record
    Custom Search Result Style Based On SharePoint Xslt Search Result Style
    软考信息系统项目管理师考试记录
    什么是Microsoft SharePoint 2010
  • 原文地址:https://www.cnblogs.com/MyUniverse/p/13137584.html
Copyright © 2020-2023  润新知