如何使用多个参数将-ldflags传递给exec.Command

时间:2018-08-28 15:18:00

标签: go ldflags

我有一个相当简单的go文件,它构建了一些用go编写的内部工具。在我决定将-ldflags添加到我的build命令之前,它一直运行良好。以下是格式化go build命令的代码段。

var cmd *exec.Cmd
file := fmt.Sprintf("%s.%s.%s", p.Bin, e.OS, e.Arch)
if len(p.Flags) > 0 {
    ldflags := ""
    for _, f := range p.Flags {
        if len(ldflags) > 0 {
            ldflags = ldflags + " "
        }
        ldflags = ldflags + f.Flag
    }
    ldflags = "\"" + ldflags + "\""
    fmt.Println("go", "build", "-v", "-a", "-ldflags", ldflags, "-o", fmt.Sprintf("/tmp/bin/%s", file), ".")
    cmd = exec.Command("go", "build", "-a", "-ldflags", ldflags, "-o", fmt.Sprintf("/tmp/bin/%s", file), ".")
} else {
    fmt.Println("go", "build", "-v", "-a", "-o", fmt.Sprintf("/tmp/bin/%s", file), ".")
    cmd = exec.Command("go", "build", "-a", "-o", fmt.Sprintf("/tmp/bin/%s", file), ".")
        }
cmd.Dir = p.Pkg
cmd.Stdout = ioutil.Discard
cmd.Stderr = os.Stdout
cmd.Env = append(cleanEnv(),
    fmt.Sprintf("GOOS=%s", e.OS),
    fmt.Sprintf("GOARCH=%s", e.Arch),
)

if err := cmd.Run(); err != nil {
    return err
}

我的标志被定义为像这样的简单字符串

[]flagarg{
    {Flag:"-X main.buildstamp=`date -u '+%Y-%m-%d_%I:%M:%S%p'`"},
    {Flag:"-X main.githash=`git rev-parse --short HEAD`"},
}

以下是我打印时的输出

go build -v -a -ldflags "-X main.buildstamp=`date -u
'+%Y-%m-%d_%I:%M:%S%p'` -X main.githash=`git rev-parse --short HEAD`"
-o /tmp/bin/bro.linux.amd64 .

当我将其粘贴到CLI中时,上述命令有效,但是当我通过go脚本运行此go build时,该命令将失败。当我说失败时,是指未设置变量githashbuildstamp。复制和粘贴命令确实会按预期设置这些变量。

我认为引号一定有问题,我尝试过更改引号,但是我无法正常工作。我开始认为我正在走错路,这一定是使它正常工作的更好方法。

1 个答案:

答案 0 :(得分:2)

command substitution (backticks)可能存在此问题;它没有达到您的期望,因为它是Shell的功能,而不是“ go build”命令。

[]flagarg{
    {Flag:"-X main.buildstamp=`date -u '+%Y-%m-%d_%I:%M:%S%p'`"},
    // Bash command subst ----^------------------------------^

尝试将打印的命令行作为“ bash -c”的单个字符串参数执行,例如:

cmd = exec.Command("bash", "-c", "go build -v -a ...")

您可能还想考虑使用$(...)形式的bash命令替换(我认为它更容易阅读),下面是一个简单的示例来演示:

cmdline := "echo \"The time is now '$(date)'!\""
out, err := exec.Command("bash", "-c", cmdline).Output()
if err != nil {
    panic(err)
}
fmt.Println(string(out))
// The time is now 'Tue Aug 28 09:33:34 MDT 2018'!