Windows exec,Cmd.Run()未正确运行带参数的命令
go版本go1.15.6 windows/amd64 开发操作系统Windows[版本10.0.19041.630] 我有一个Go应用程序,其中我使用exec.Cmd.Run()运行AWS CLI。我构建Cmd类并填充参数 在运行Cmd之前,我使用.String()方法查看要运行的命令。如果我接受这个值,将它复制到shell,那么命令执行时不会修改提供给我的输出,也不会报告任何问题 但是,当我运行该命令时,它无法返回错误。当我调试脚本时,它失败了,因为它说AWS CLI说某个参数不正确 问题:Windows exec,Cmd.Run()未正确运行带参数的命令,windows,go,cmd,Windows,Go,Cmd,go版本go1.15.6 windows/amd64 开发操作系统Windows[版本10.0.19041.630] 我有一个Go应用程序,其中我使用exec.Cmd.Run()运行AWS CLI。我构建Cmd类并填充参数 在运行Cmd之前,我使用.String()方法查看要运行的命令。如果我接受这个值,将它复制到shell,那么命令执行时不会修改提供给我的输出,也不会报告任何问题 但是,当我运行该命令时,它无法返回错误。当我调试脚本时,它失败了,因为它说AWS CLI说某个参数不正确 问题:
cmd := &exec.Cmd{
Path: awsPath,
Args: args,
Stdout: &stdout,
Stderr: &stderr,
}
fmt.Printf("Command: %s\n", cmd.String())
// c:\PROGRA~1\Amazon\AWSCLIV2\aws.exe --profile testprofile --region us-east-1 --output json ec2 describe-network-interfaces --filters Name=group-id,Values=sg-abc123
// Running above works 100% of the time if ran from a shell window
err := cmd.Run()
// always errors out saying the format is incorrect
问题的复制
来源:
您看到的是相反的情况,但问题是相同的:对打印的命令字符串进行眼珠观察并不会显示确切的可执行路径(是否存在恶意空格或不可打印字符?),与参数(恶意字符?)相同
使用fmt.Printf(“cmd:%q\n”,cmd.Path)
来显示任何隐藏的unicode字符等,并对每个参数使用相同的技术。编辑:
我已经找到了您遇到的问题的根本原因:
因此,如果您已声明Cmd.Path:=“/usr/local/bin/aws”
,则必须声明Cmd。Args
如下:Args:[]字符串{”、“s3”、“help”},
因为Args
在上面的文档链接中包含命令作为Args[0]
。
最后,我认为您可以像这样简单有效地执行命令:
package main
import (
"bytes"
"fmt"
"os/exec"
)
func main() {
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
name := "/usr/local/bin/aws"
arg := []string{"s3", "help"}
cmd := exec.Command(name, arg...)
cmd.Stderr = stderr
cmd.Stdout = stdout
fmt.Printf("Command: %q\n", cmd.String())
err := cmd.Run()
if err != nil {
fmt.Println("Error: ", stderr.String())
}
fmt.Println("Output: ", stdout.String())
}
=========
$ go run main.go
Command: "/usr/local/bin/aws s3 help"
完成。参考我们无法确定当您不显示参数和awsPath的格式时,您的
args
和awsPath
的格式有哪些错误。请您再显示一点代码,以便我可以重新生成并了解您的情况,好吗?您的控制台中的错误输出是什么?@JimB,我猜您的意思是“我们无法判断什么是错误的”?这是我的错,我认为提供输出对于值是什么是明确的。我编辑了我的答案,加入了一个演示问题的围棋场。但是,请注意,它不能完全联机运行。我建议使用%q
例如fmt.Printf(“命令:%q\n”,cmd.String())
。这将引用字符串-但也会显示任何不可打印和/或不正确的unicode字符,这些字符会使API出错,但如果使用%s
,则不会被检测到。Tks@colm.anseo,我已编辑了我的答案,并使用您的建议进行改进,Tks@colm.anseo我非常感激!我已经注意到了这一点,将来也会这样做@我会在早上试一试,看看它落在哪里。我感谢你的帮助。
// Path is the path of the command to run.
//
// This is the only field that must be set to a non-zero
// value. If Path is relative, it is evaluated relative
// to Dir.
Path string
// Args holds command line arguments, including the command as **Args[0]**.
// If the Args field is empty or nil, Run uses {Path}.
//
// In typical use, both Path and Args are set by calling Command.
Args []string
package main
import (
"bytes"
"fmt"
"os/exec"
)
func main() {
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
name := "/usr/local/bin/aws"
arg := []string{"s3", "help"}
cmd := exec.Command(name, arg...)
cmd.Stderr = stderr
cmd.Stdout = stdout
fmt.Printf("Command: %q\n", cmd.String())
err := cmd.Run()
if err != nil {
fmt.Println("Error: ", stderr.String())
}
fmt.Println("Output: ", stdout.String())
}
=========
$ go run main.go
Command: "/usr/local/bin/aws s3 help"