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
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 北京时间10月1日,2017-18赛季季前赛揭幕战今天正式打响,金州勇士队主场以102比108不敌胜丹佛掘金。不过...
    coco9981阅读 411评论 0 2
  • http://blog.csdn.net/david21984/article/details/57451917 ...
    紫色冰雨阅读 332评论 0 1
  • 由于公司电脑更换,特此记录下之前保存的记录 afnetwork封装: https://github.com/shy...
    chushen61阅读 783评论 0 2
  • 记得刚买回来的时候绿枝哥哥还是只高冷的龟,就静静地趴在那里,任燕草弟弟爬上爬下,翻来翻去。所以他叫绿枝,弟弟叫燕草...
    临鸢羡鱼阅读 245评论 0 0
  • 在泰国的七周(自己多玩耍了一周),有过很多人问我,你为什么选择做志愿者而不是旅游?我的回答一直是:“我想要的是深入...
    744c7e4d4244阅读 397评论 0 0