运行 SCP via go exec.cmd
Running SCP via go exec.cmd
我正在尝试通过 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 和 ssh 坚持从 tty(或伪 tty)读取密码
来自远程会话的标准输入不是这个,所以它不会工作
标准的 go golang.org/x/crypto/ssh package does support sending passwords so presumably has a work around. 所以扩展现有的 go ssh 支持可能并不困难
但是,总有一个基于外部程序的解决方法!正如所讨论的 here,
这涉及使用 sshpass
程序
我假设你在 Linux。如果您想从命令行向 scp
传递密码,最好的方法是使用 sshpass
。它应该可以从主要 Linux 发行版的默认包存储库中安装,只需使用 apt
或 yum
安装即可。语法是 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" 软件包更易于用于此类文件传输。您可以找到一个如何使用它的简单示例 。请注意,在客户端配置中使用 nil
作为 HostKeyCallback
已被弃用 - 如果您绝对需要接受所有主机密钥,请使用 HostKeyCallback: ssh.InsecureIgnoreHostKey()
。
我正在尝试通过 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 和 ssh 坚持从 tty(或伪 tty)读取密码
来自远程会话的标准输入不是这个,所以它不会工作
标准的 go golang.org/x/crypto/ssh package does support sending passwords so presumably has a work around.
但是,总有一个基于外部程序的解决方法!正如所讨论的 here,
这涉及使用 sshpass
程序
我假设你在 Linux。如果您想从命令行向 scp
传递密码,最好的方法是使用 sshpass
。它应该可以从主要 Linux 发行版的默认包存储库中安装,只需使用 apt
或 yum
安装即可。语法是 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" 软件包更易于用于此类文件传输。您可以找到一个如何使用它的简单示例 nil
作为 HostKeyCallback
已被弃用 - 如果您绝对需要接受所有主机密钥,请使用 HostKeyCallback: ssh.InsecureIgnoreHostKey()
。