我正在尝试通过golang的exec.cmd作为命令运行scp,因为可用于scp传输的非官方实现对我不起作用。 Scp一直执行到询问密码为止,然后我无法将数据写入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会话传输二进制文件的方法? 预先感谢。
答案 0 :(得分:1)
我假设您使用的是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”包更容易用于这种文件传输。您可以找到一个简单的示例here。请注意,不建议在客户端配置中将nil
用于HostKeyCallback
-如果绝对需要接受所有主机密钥,请使用HostKeyCallback: ssh.InsecureIgnoreHostKey()
。
答案 1 :(得分:0)
scp和ssh坚持从tty(或伪tty)读取密码
来自远程会话的标准输入不是这样,所以它将不起作用
标准的go golang.org/x/crypto/ssh软件包确实支持发送密码,因此可以解决。 scp is implemented as a server that is invoked by ssh,因此扩展现有的go ssh支持并不困难
但是,总是有一个基于外部程序的解决方法!如here所述,
这涉及使用<bean id="entityManagerFactory"
程序