使用crypto/ssh的golang scp文件 [英] golang scp file using crypto/ssh

查看:103
本文介绍了使用crypto/ssh的golang scp文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过ssh下载远程文件以下方法可以在Shell上正常工作

I'm trying to download a remote file over ssh The following approach works fine on shell

ssh hostname "tar cz /opt/local/folder" > folder.tar.gz

但是在golang上使用相同的方法会在输出工件大小上产生一些差异.例如,具有纯外壳的相同文件夹将生成工件gz文件179B,而与go脚本178B相同.我认为io.Reader缺少某些内容,或者会话已提前关闭.请问大家帮忙.

However the same approach on golang giving some difference in output artifact size. For example the same folders with pure shell produce artifact gz file 179B and same with go script 178B. I assume that something has been missed from io.Reader or session got closed earlier. Kindly ask you guys to help.

这是我的脚本示例:

func executeCmd(cmd, hostname string, config *ssh.ClientConfig, path string) error {
    conn, _ := ssh.Dial("tcp", hostname+":22", config)
    session, err := conn.NewSession()
    if err != nil {
        panic("Failed to create session: " + err.Error())
    }

    r, _ := session.StdoutPipe()
    scanner := bufio.NewScanner(r)

    go func() {
        defer session.Close()

        name := fmt.Sprintf("%s/backup_folder_%v.tar.gz", path, time.Now().Unix())
        file, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
        if err != nil {
            panic(err)
        }
        defer file.Close()
        for scanner.Scan() {
            fmt.Println(scanner.Bytes())
            if err := scanner.Err(); err != nil {
                fmt.Println(err)
            }

            if _, err = file.Write(scanner.Bytes()); err != nil {
                log.Fatal(err)

            }
        }
    }()

    if err := session.Run(cmd); err != nil {
        fmt.Println(err.Error())
        panic("Failed to run: " + err.Error())
    }

    return nil
}

谢谢!

推荐答案

bufio.Scanner 用于换行符分隔的文本.根据文档,扫描程序将删除换行符,并从二进制文件中删除所有 10 .

bufio.Scanner is for newline delimited text. According to the documentation, the scanner will remove the newline characters, stripping any 10s out of your binary file.

您不需要goroutine进行复制,因为您可以使用 session.Start 异步启动该过程.

You don't need a goroutine to do the copy, because you can use session.Start to start the process asynchronously.

您可能也不需要使用bufio.您应该使用io.Copy复制文件,该文件在ssh客户端本身已经完成的所有缓冲中已经具有内部缓冲区.如果需要额外的缓冲区以提高性能,请将会话输出包装在 bufio.Reader

You probably don't need to use bufio either. You should be using io.Copy to copy the file, which has an internal buffer already on top of any buffering already done in the ssh client itself. If an additional buffer is needed for performance, wrap the session output in a bufio.Reader

最后,您返回一个错误值,因此请使用它,而不是在常规错误情况下惊慌.

Finally, you return an error value, so use it rather than panic'ing on regular error conditions.

conn, err := ssh.Dial("tcp", hostname+":22", config)
if err != nil {
    return err
}

session, err := conn.NewSession()
if err != nil {
    return err
}
defer session.Close()

r, err := session.StdoutPipe()
if err != nil {
    return err
}

name := fmt.Sprintf("%s/backup_folder_%v.tar.gz", path, time.Now().Unix())
file, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
    return err
}
defer file.Close()

if err := session.Start(cmd); err != nil {
    return err
}

n, err := io.Copy(file, r)
if err != nil {
    return err
}

if err := session.Wait(); err != nil {
    return err
}

return nil

这篇关于使用crypto/ssh的golang scp文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆