drfqfuhej48511519 2018-11-12 05:29
浏览 177
已采纳

在Go中通过SSH发送文件

I found this answer before posting this question but the answer is not clear to me.

Here is the code of the answer:

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

I don't understand relation between the cmd variable and io.Copy, where and how does it know which file to copy. I like the idea of using io.Copy but i do not know how to create the file via ssh and start sending content to it using io.Copy.

  • 写回答

1条回答 默认 最新

  • dtot74529 2018-11-12 08:52
    关注

    Here is a minimal example on how to use Go as an scp client:

    config := &ssh.ClientConfig{
        User: "user",
        Auth: []ssh.AuthMethod{
            ssh.Password("pass"),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
    
    client, _ := ssh.Dial("tcp", "remotehost:22", config)
    defer client.Close()
    
    session, _ := client.NewSession()
    defer session.Close()
    
    file, _ := os.Open("filetocopy")
    defer file.Close()
    stat, _ := file.Stat()
    
    wg := sync.WaitGroup{}
    wg.Add(1)
    
    go func() {
        hostIn, _ := session.StdinPipe()
        defer hostIn.Close()
        fmt.Fprintf(hostIn, "C0664 %d %s
    ", stat.Size(), "filecopyname")
        io.Copy(hostIn, file)
        fmt.Fprint(hostIn, "\x00")
        wg.Done()
    }()
    
    session.Run("/usr/bin/scp -t /remotedirectory/")
    wg.Wait()
    

    Note that I have ignored all errors only for conciseness.

    1. session.StdinPipe() will create a writable pipe for the remote host.
    2. fmt.Fprintf(... "C0664 ...") will signal the start of a file with 0664 permission, stat.Size() size and the remote filename filecopyname.
    3. io.Copy(hostIn, file) will write the contents of file into hostIn.
    4. fmt.Fprint(hostIn, "\x00") will signal the end of the file.
    5. session.Run("/usr/bin/scp -qt /remotedirectory/") will run the scp command.

    Edit: Added waitgroup per OP's request

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求一下解题思路,完全不懂
  • ¥15 tensorflow
  • ¥15 densenet网络结构中,特征以cat方式复用后是怎么进行误差回传的
  • ¥15 STM32G471芯片spi设置了8位,总是发送16位
  • ¥15 R语言并行计算beta-NTI中tree文件的类型
  • ¥15 如何解读marsbar导出的ROI数据?
  • ¥20 求友友协助弄一下基于STC89C52单片机的声光控制灯原理图
  • ¥15 arduino双向交通灯设计
  • ¥15 有没有会粒子群算法的大能(○゜ε^○)求带不会出收敛图😭
  • ¥15 Matlab读取根元素出错