美文网首页
Golang sftp 实现,并发拷贝文件

Golang sftp 实现,并发拷贝文件

作者: 彩色代码 | 来源:发表于2020-07-21 15:32 被阅读0次

    本人通过ssh公钥、私钥先实现可以通过ssh登录到目标机器

    ssh root@10.1.1.1
    

    注意这里是免密登录

    然后通过指定公钥的方式,实现golang sftp协议传输文件

    package main
    //go run ops-sftp.go hosts 10.1.1.1,10.1.1.2 /workspace/test/w.txt /workspace/test/source.txt
    import (
        "fmt"
        "ops-client/utils/sshClient"
        "os"
        "strings"
        "sync"
        "time"
    )
    
    func main() {
        actionType:=os.Args[1]
        ips:=os.Args[2]
        ip_array:=strings.Split(ips,",")
        writeFile:=os.Args[3]
        sourceFile:=os.Args[4]
        host, _ := os.Hostname()
        privateKeyFile := ""
        if host == "MacOS.local" {
            privateKeyFile = "/Users/my/.ssh/id_rsa"
        } else {
            privateKeyFile = "/home/www/.ssh/id_rsa"
        }
        var wg sync.WaitGroup
        tmpSourceFile:=sourceFile
        for _, ip := range ip_array {
            wg.Add(1)
            if actionType=="hosts" {
                tmpSourceFile=sourceFile+"."+ip
            }
            //ip="10.211.163.81"
            go func(ip, privateKeyFile,writeFile,tmpSourceFile string) {
                defer wg.Add(-1)
                err := sshClient.Sftp(ip, privateKeyFile,writeFile,tmpSourceFile)
                if err!=nil {
                    time.Sleep(2 * time.Second)
                    err := sshClient.Sftp(ip, privateKeyFile,writeFile,tmpSourceFile)
                    if err!=nil {
                        fmt.Println(ip,"\t",err)
                        os.Exit(1)
                    }
                }
            }(ip, privateKeyFile,writeFile,tmpSourceFile)
            time.Sleep(10 * time.Millisecond)
        }
        wg.Wait()
    }
    
    

    自定义 sshClient 包,新建文件 common.go

    package sshClient
    
    import (
       "bytes"
       "golang.org/x/crypto/ssh"
       "io"
       "io/ioutil"
       "log"
       "os"
       "time"
       "github.com/pkg/sftp"
    )
    
    func CollectTest(ip string,privateKeyFile string) bool {
       remoteIP := ip+":22"
       user := "root"
       privateKeyBytes, err := ioutil.ReadFile(privateKeyFile)
       if err != nil {
           log.Fatal(err)
       }
       //privateKeyBytes:=[]byte(privateKeyString)
       key, err := ssh.ParsePrivateKey(privateKeyBytes)
       if err != nil {
           log.Fatal(err)
       }
    
       config := &ssh.ClientConfig{
           User: user,
           Auth: []ssh.AuthMethod{
               // Use the PublicKeys method for remote authentication.
               ssh.PublicKeys(key),
           },
           // using InsecureIgnoreHostKey() for testing purposes
           HostKeyCallback: ssh.InsecureIgnoreHostKey(),
           Timeout:1 * time.Second,
       }
    
       client, err := ssh.Dial("tcp", remoteIP, config)
       if err != nil {
           //log.Fatalf("unable to connect: %v", err)
           return false
       }
       defer client.Close()
    
       return true
    }
    
    func RunCommand(ip string,privateKeyFile string,cmdString string) (string,string,error) {
       remoteIP := ip+":22"
       user := "root"
       privateKeyBytes, err := ioutil.ReadFile(privateKeyFile)
       if err != nil {
           log.Fatal(err)
       }
       key, err := ssh.ParsePrivateKey(privateKeyBytes)
       if err != nil {
           log.Fatal(err)
       }
       config := &ssh.ClientConfig{
           User: user,
           Auth: []ssh.AuthMethod{
               ssh.PublicKeys(key),
           },
           HostKeyCallback: ssh.InsecureIgnoreHostKey(),
           Timeout:1 * time.Second,
       }
    
       client, err := ssh.Dial("tcp", remoteIP, config)
       if err != nil {
           //log.Fatalf("unable to connect: %v", err)
           return "","",err
       }
       defer client.Close()
    
       var stdOut, stdErr bytes.Buffer
       // create session
       session, err := client.NewSession();
       defer session.Close()
    
       if  err != nil {
           return "","",err
       }
       session.Stdout = &stdOut
       session.Stderr = &stdErr
       err=session.Run(cmdString)
       return stdOut.String(),stdErr.String(),err
    }
    
    func Sftp(ip,privateKeyFile,writeFile,sourceFile string) (error) {
       remoteIP := ip+":22"
       user := "root"
       privateKeyBytes, err := ioutil.ReadFile(privateKeyFile)
       if err != nil {
           log.Fatal(err)
       }
       key, err := ssh.ParsePrivateKey(privateKeyBytes)
       if err != nil {
           log.Fatal(err)
       }
       config := &ssh.ClientConfig{
           User: user,
           Auth: []ssh.AuthMethod{
               ssh.PublicKeys(key),
           },
           HostKeyCallback: ssh.InsecureIgnoreHostKey(),
           Timeout:1 * time.Second,
       }
    
       client, err := ssh.Dial("tcp", remoteIP, config)
       if err != nil {
           return err
       }
       defer client.Close()
    
       c, err := sftp.NewClient(client)
       if err != nil {
           log.Fatalf("unable to start sftp subsytem: %v", err)
       }
       defer c.Close()
    
       w, err := c.OpenFile(writeFile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE)
       if err != nil {
           return err
       }
       defer w.Close()
    
       f, err := os.Open(sourceFile)
       if err != nil {
           return err
       }
       defer f.Close()
    
       t1 := time.Now()
       n, err := io.Copy(w, f)
       if err != nil {
           return err
       }
    
       log.Printf("wrote %v bytes in %s", n, time.Since(t1))
       return nil
    }
    
    

    用法

    go run ops-sftp.go hosts 10.1.1.1,10.1.1.2 /workspace/test/w.txt /workspace/test/source.txt
    

    相关文章

      网友评论

          本文标题:Golang sftp 实现,并发拷贝文件

          本文链接:https://www.haomeiwen.com/subject/uibikktx.html