繁体   English   中英

通过go exec.cmd运行SCP

[英]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发行版上的默认软件包存储库中安装,只需使用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”包更容易用于这样的文件传输。 您可以在此处找到有关如何使用它的简单示例。 请注意,使用nilHostKeyCallback在客户端的配置已经过时-使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM