[英]Running SCP via go exec.cmd
我试图通过golang的exec.cmd作为命令运行scp,因为可用于scp传输的非官方实现对我不起作用。 Scp一直执行到询问密码为止,然后我无法将数据写入stdin。 stdin是否有可能重定向到其他地方?
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会话传输二进制文件的方法? 提前致谢。
我假设您使用的是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()
如果你绝对需要接受所有主机密钥。
scp和ssh坚持从tty(或psuedo tty)读取密码
来自远程会话的标准输入不是这个,所以它将不起作用
标准的golang.org/x/crypto/ssh软件包确实支持发送密码,因此可以解决。 scp被实现为由ssh调用的服务器,因此扩展现有的go ssh支持可能并不困难
但是,始终存在基于外部程序的解决方法! 作为讨论在这里 ,这包括使用sshpass
程序
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.