Go调用exec.Command执行带ProxyCommand的SSH命令报错如何修复?
问题解决方法
错误原因
- 你在Shell中执行命令时用的双引号是Shell的语法,作用是告知Shell引号内的所有内容是单个参数,不要按空格拆分。但Go的
exec.Command默认不会启动Shell解析语法,你传入的双引号会被当成参数的一部分传给ssh程序,反而导致参数解析错误。 strings.Fields会无脑按所有空白字符拆分字符串,不会识别引号的包裹作用,会把你本应作为单个参数的ProxyCommand内容拆分为多个独立参数,进一步导致参数错位。- 额外注意:你的代码中存在笔误,将
myprivatekey.pem错写为myprivateksy.pem,也会导致认证失败。
正确实现
推荐手动拆分参数,完全规避字符串拆分和引号解析问题:
func (s SSH) Tunnel() error { // 手动定义所有ssh参数,不需要加Shell用的外层双引号 args := []string{ "-i", "/home/myuser/.ssh/myprivatekey.pem", "ec2-user@i-00xxxxxxxxxx", "-o", `ProxyCommand=aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'`, } command := exec.Command("ssh", args...) command.Stderr = os.Stderr command.Stdout = os.Stdout command.Stdin = os.Stdin return command.Run() }
如果你确实需要通过Shell执行命令(不推荐,存在命令注入风险),也可以直接把整条Shell命令传给sh -c:
func (s SSH) Tunnel() error { cmdStr := `ssh -i /home/myuser/.ssh/myprivatekey.pem ec2-user@i-00xxxxxxxxxx -o ProxyCommand="aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"` command := exec.Command("sh", "-c", cmdStr) command.Stderr = os.Stderr command.Stdout = os.Stdout command.Stdin = os.Stdin return command.Run() }
内容的提问来源于stack exchange,提问作者Matteo
相关产品推荐
相关产品推荐

