go exec cmd /c 处理空格和双引号问题,大家有什么好办法吗?

查看 62|回复 3
作者:LonnyWong   
开源 issue: https://github.com/trzsz/trzsz-ssh/issues/46
复现 demo:
package main
import (
        "fmt"
        "os/exec"
)
func main() {
        command := `"C:\WINDOWS\System32\OpenSSH\ssh.exe" -V`
        // command = `"C:\Program Files\ssh.exe" -V`
        cmd := exec.Command("cmd", "/c", command)
        output, _ := cmd.CombinedOutput()
        fmt.Println(string(output))
}
错误输出:
'\"C:\WINDOWS\System32\OpenSSH\ssh.exe\"' is not recognized as an internal or external command,
operable program or batch file.
原始问题,用户在 ~/.ssh/config 中配置任意的 ProxyCommand,要用 os/exec 来执行它,并且获取它的标准输出。用 cmd /c 是想避免解释每一个具体的参数是什么,有双引号,有空格,有转义,要准确地解释出每一个参数不简单啊。
大佬们有什么好想法吗?

Cmd, command, exec, ssh

geelaw   
为什么要多此一举透过 cmd ?另外从 go 的 API 设计可以看出它必须用 Unix 的方式传入 argv ,而不是 Windows 的 command line 。而 cmd 是按照 command line 而不是 argv 读取命令的,因为同一组 argv 有无限种不同的 command line 表示,而且这些会被 cmd 理解为不同的意思,所以不存在可靠的用 go 的 exec 调用 cmd 的方法。
如果你要调用 ssh 并传入 -V ,可以直接传入合适的 argv 。
geelaw   
例子:
exec.Command("C:\\WINDOWS\\System32\|OpenSSH\\ssh.exe", "-V")
go 和 ssh 理应 Windows 上能正确互转 command line 和 argv 。
LonnyWong
OP
  
@geelaw 因为 command 是未知的,如果你想输入准确的 argv ,那就需要先从一个字符串中解释出准确的 argv 来。
只是简单的空格分隔是不够的,因为有些参数本身可能就存在空格,然后还会有双引号包起来,然后双引号自己又可能会存在转义。如何保证从字符串中解释出来的参数是准确的?
您需要登录后才可以回帖 登录 | 立即注册

返回顶部