Windows exec,Cmd.Run()未正确运行带参数的命令

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说某个参数不正确 问题:

go版本go1.15.6 windows/amd64 开发操作系统Windows[版本10.0.19041.630]

我有一个Go应用程序,其中我使用exec.Cmd.Run()运行AWS CLI。我构建Cmd类并填充参数

在运行Cmd之前,我使用.String()方法查看要运行的命令。如果我接受这个值,将它复制到shell,那么命令执行时不会修改提供给我的输出,也不会报告任何问题

但是,当我运行该命令时,它无法返回错误。当我调试脚本时,它失败了,因为它说AWS CLI说某个参数不正确

问题:

  • 是否可以看到正在运行的内容的100%原始表示?它与.String()的返回值不匹配
  • 有没有更好的方法来调用我缺少的操作系统级命令
  • 实例:

    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"