golang 批量scp 远程传输文件

/ go / 没有评论 / 2592浏览

golang 批量scp 远程传输文件

// main.go
package main

import (
    "fmt"
    "log"
    "net"
    "os"
    "path"
    "time"

    "github.com/pkg/sftp"
    "golang.org/x/crypto/ssh"
)
func sshconnect(user, password, host string, port int) (*ssh.Session, error) {
    var (
        auth         []ssh.AuthMethod
        addr         string
        clientConfig *ssh.ClientConfig
        client       *ssh.Client
        session      *ssh.Session
        err          error
    )
    // get auth method
    auth = make([]ssh.AuthMethod, 0)
    auth = append(auth, ssh.Password(password))

    clientConfig = &ssh.ClientConfig{
        User:    user,
        Auth:    auth,
        Timeout: 30 * time.Second,
    }

    // connet to ssh
    addr = fmt.Sprintf("%s:%d", host, port)

    if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
        return nil, err
    }

    // create session
    if session, err = client.NewSession(); err != nil {
        return nil, err
    }

    return session, nil
}

func sftpconnect(user, password, host string, port int) (*sftp.Client, error) {
    var (
        auth         []ssh.AuthMethod
        addr         string
        clientConfig *ssh.ClientConfig
        sshClient    *ssh.Client
        sftpClient   *sftp.Client
        err          error
    )
    // get auth method
    auth = make([]ssh.AuthMethod, 0)
    auth = append(auth, ssh.Password(password))

    clientConfig = &ssh.ClientConfig{
        User:    user,
        Auth:    auth,
        Timeout: 30 * time.Second,
              //这个是问你要不要验证远程主机,以保证安全性。这里不验证
        HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
            return nil
        },
    }

    // connet to ssh
    addr = fmt.Sprintf("%s:%d", host, port)

    if sshClient, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
        return nil, err
    }

    // create sftp client
    if sftpClient, err = sftp.NewClient(sshClient); err != nil {
        return nil, err
    }

    return sftpClient, nil
}


//单个copy
func scpCopy(localFilePath, remoteDir string) error {
    var (
        sftpClient *sftp.Client
        err        error
    )
    // 这里换成实际的 SSH 连接的 用户名,密码,主机名或IP,SSH端口
    sftpClient, err = sftpconnect("user", "passwd", "目的机器的ip", 目的机器的端口)
    if err != nil {
        log.Println("scpCopy:", err)
        return err
    }
    defer sftpClient.Close()
    srcFile, err := os.Open(localFilePath)
    if err != nil {
        log.Println("scpCopy:", err)
        return err
    }
    defer srcFile.Close()

    var remoteFileName = path.Base(localFilePath)
    dstFile, err := sftpClient.Create(path.Join(remoteDir, remoteFileName))
    if err != nil {
        log.Println("scpCopy:", err)
        return err
    }
    defer dstFile.Close()

    buf := make([]byte, 1024)
    for {
        n, _ := srcFile.Read(buf)
        if n == 0 {
            break
        }
        dstFile.Write(buf[0:n])
    }
    return nil
}

这里是批量copy

//批量copy
func scpListCopy(cinfos []CouponInfo) error {
    var localFilePath, remoteDir string

    // 这里换成实际的 SSH 连接的 用户名,密码,主机名或IP,SSH端口
    sshftpClient := NewSftpClient()

    // 用来测试的本地文件路径 和 远程机器上的文件夹
    for _, v := range cinfos {
        for i := 0; i < len(v.Coupons); i++ {
            localFilePath = v.Coupons[i].Addr
            remoteDir = "目的地址"

            srcFile, err := os.Open(localFilePath)
            if err != nil {
                logger.Println("scpListCopy1:", err)
                return err
            }
            defer srcFile.Close()

            var remoteFileName = path.Base(localFilePath)
            dstFile, err := sshftpClient.Create(path.Join(remoteDir, remoteFileName))
            if err != nil {
                logger.Println("scpListCopy2:", err)
                return err
            }
            defer dstFile.Close()

            buf := make([]byte, 1024)
            for {
                n, _ := srcFile.Read(buf)
                if n == 0 {
                    break
                }
                dstFile.Write(buf[0:n])
            }
        }
    }
    return nil
}
/*
NewSftpClient 这个方法,此文件应该有个全局变量
var sftpClient *sftp.Client
全局变量,保证不会出现tcp关闭不掉的错误,这个恶心的错误就是:
 ssh: unexpected packet in response to channel open: <nil>
*/
func NewSftpClient() *sftp.Client {
    var err error
    if sftpClient == nil {
        sftpClient, err = sftpconnect("duyq", "duyuqing123456", "10.250.129.22", 22)
        if err != nil {
            logger.Fatalln("NewSftpClient:", err)
        }
    }
    return sftpClient
}