使用crypto / ssh的golang scp文件

时间:2016-07-07 09:58:54

标签: go ssh scp

我正在尝试通过ssh下载远程文件 以下方法适用于shell

Byte[]

然而,golang上的相同方法在输出工件大小上有所不同。例如,具有纯shell的相同文件夹产生伪像gz文件179B并且与go脚本178B相同。 我假设io.Reader错过了某些内容,或者会话早先关闭了。请你帮忙。

以下是我的脚本示例:

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

谢谢!

2 个答案:

答案 0 :(得分:4)

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

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

您可能也不需要使用bufio。您应该使用io.Copy来复制文件,该文件已经在ssh客户端本身已经完成的任何缓冲之上已经有一个内部缓冲区。如果性能需要额外的缓冲区,请将会话输出包装在bufio.Reader

最后,您返回一个错误值,因此请在常规错误条件下使用它而不是恐慌。

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

答案 1 :(得分:-1)

您可以尝试这样做:

r, _ := session.StdoutPipe()
reader := bufio.NewReader(r)

go func() {
    defer session.Close()
    // open file etc

    // 10 is the number of bytes you'd like to copy in one write operation
    p := make([]byte, 10)
    for {
        n, err := reader.Read(p)
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatal("err", err)
        }

        if _, err = file.Write(p[:n]); err != nil {
            log.Fatal(err)
        }
    }
}()

确保您的goroutine正确同步,以便将输出完整写入文件。