【问题标题】:Running SCP via go exec.cmd通过 go exec.cmd 运行 SCP
【发布时间】:2018-12-09 09:11:20
【问题描述】:

我正在尝试通过 golang 的 exec.cmd 将 scp 作为命令运行,因为可用于 scp 传输的非官方实现对我不起作用。 Scp 一直执行,直到它要求输入密码,然后我无法将数据写入标准输入。是否有可能将标准输入重定向到其他地方?

var cmd *exec.Cmd
if m.IsDir() {
    cmd = exec.Command("scp", "-r", src, user+"@"+client.Host+":"+dest)
} else {
    cmd = exec.Command("scp", src, user+"@"+client.Host+":"+dest)
}

cmdWriter, err := cmd.StdinPipe()
if err != nil {
    return err
}

err = cmd.Start()

if cred.Typ() == "PW" {
    cmdWriter.Write( []byte(cred.Data()+"\n") )
} else {
    log.Println( "credential typ not supported" )
}

err = cmd.Wait()
log.Println( "done" )
return err

将 cmd.Stdin 设置为 os.Stdin 可以,但当然我必须手动输入密码,这不是我想要的。 还是您总体上不推荐这种方式来运行 scp?我能够在服务器上运行简单的 SSH 命令(使用“golang.org/x/crypto/ssh”)。有没有办法仅通过 SSH 会话传输二进制文件? 提前致谢。

【问题讨论】:

  • 看看如何实现 scp:github.com/viant/toolbox/blob/master/ssh
  • 谢谢,但我真的在寻找一个简单的解决方案。我已经尝试了一些 scp 实现。
  • 你看过cmd是否有输出?它不一定会返回,因为它可能会显示错误的密码或其他内容。
  • 不写入 stdIn 只是没有效果。我什至尝试将输入设置为 os.stdin,然后使用 os.stdin.write 进行写入,但它不起作用。它只有在我手动输入时才有效。我现在非常有信心 scp 创建一个子进程,一旦它将 user@10.1.1.2' 密码写入输出,就不再使用旧管道。

标签: go ssh scp


【解决方案1】:

我假设您使用的是 Linux。如果您想从命令行将密码传递给scp,最好的方法是使用sshpass。它应该可以从主要 Linux 发行版上的默认软件包存储库安装,只需使用 aptyum 安装即可。语法为sshpass -p [password] scp ...

在这里,我生成了一个 bash 会话并将命令从 StdinPipe 传递给它:

func main() { 
    cmd := exec.Command("bash")
    cmdWriter, _ := cmd.StdinPipe()
    cmd.Start()

    cmdString := fmt.Sprintf("sshpass -p %s scp -r %s %s@%s:%s", password, src, user, client, dest)

    cmdWriter.Write([]byte(cmdString + "\n"))
    cmdWriter.Write([]byte("exit"    + "\n"))

    cmd.Wait()
}

为了简洁起见,我忽略了错误并稍微简化了您的代码。


但是,“github.com/pkg/sftp”包更容易用于像这样的文件传输。你可以找到一个简单的例子来说明如何使用它here。请注意,不推荐在客户端配置中将 nil 用于 HostKeyCallback - 如果您绝对需要接受所有主机密钥,请使用 HostKeyCallback: ssh.InsecureIgnoreHostKey()

【讨论】:

  • github 包看起来是最好的选择。我的软件必须以尽可能少的依赖项运行,因此 sshpass 并不是一个真正的选择。谢谢。
【解决方案2】:

scp 和 ssh 坚持从 tty(或伪 tty)读取密码

来自远程会话的标准输入不是这个,所以它不会工作

标准的 go golang.org/x/crypto/ssh 包确实支持发送密码,所以大概可以解决。 scp is implemented as a server that is invoked by ssh 所以可能扩展现有的 go ssh 支持并不困难

但是,始终存在基于外部程序的解决方法!正如here 所讨论的, 这涉及使用sshpass 程序

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-02
    • 2017-12-04
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 2014-09-03
    相关资源
    最近更新 更多