我不确定这是否是所调用程序的问题,还是该问题是由我调用程序的方式引起的。因此,我从源代码开始。
我需要从程序中调用ssh(如果您对我在下面提到它们的原因感兴趣),但是ssh会自动退出。
当我打电话ssh -v user@remotehost
从壳此成功:
但是当我在程序中执行相同操作时(myssh -v user@remotehost
,只会发生这种情况:
既没有显示stderr上的调试输出,也没有到达远程主机外壳。
这是我的源代码:
package main
import (
"fmt"
"log"
"os"
"os/exec"
)
func main() {
params := os.Args[1:]
fmt.Printf("passing this to ssh: %s\n", params)
cmd := exec.Command("ssh", params...)
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
}
原因是为什么我编写此代码:我使用Ansible调用ssh。我需要“操纵” Ansible传递给ssh的参数。到目前为止,我在OpenSSH和Ansible邮件列表中询问过,OpenSSH和Ansible中没有任何方法可以更改参数(对于其他参数,但我不需要的)。我得到并希望实现的最佳建议是为Ansible提供一个替代的ssh命令,使用它来接收和修改参数并将其传递给真实的ssh。
答案 0 :(得分:1)
您是从Stdout
捕获Stderr
和cmd
吗?这是命令的各个输出发送到的位置。 Commit d327618的文档中有一个很好的例子。
在你的情况,你也想设置Stdin
这样就可以例如通过密码。
下面是一个非常基本的例子,根据您的代码:
package main
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
)
func main() {
params := os.Args[1:]
fmt.Println("Passing this to ssh: %s", params)
var stdin bytes.Buffer
var stdout bytes.Buffer
var stderr bytes.Bufer
cmd := exec.Command("ssh", params...)
cmd.Stdin = &stdin
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
fmt.Println("Stdout: %s", stdout.String())
fmt.Println("stderr: %s", stderr.String())
}
由于stdin
,stdout
,和stderr
是所有bytes.Buffer
S,则可以读取和由它们就像任何其他缓冲器写入。
您也可能要考虑使用golang.org/x/crypto/ssh
包,它提供了一种天然SSH接口,用于转到而不是使用子过程。