docker run -w从go脚本运行时发出意外错误

时间:2018-02-10 18:32:45

标签: docker go

我正在编写一个非常简单的脚本,它只是通过docker为go应用程序格式化构建命令。它格式化命令如下:

docker run --rm -v c:/Users/me/go/src/goapp:/go/src/goapp -w /go/src/goapp -e GOOS=os -e GOARCH=arch image go build -v -o outputname

运行时,我得到以下内容:

  

docker:来自守护进程的错误响应:工作目录'/ go / src / goapp'无效,它必须是绝对路径

我尝试重新格式化它:

docker run --rm -v="c:/Users/me/go/src/goapp:/go/src/goapp" -w="/go/src/goapp" -e="GOOS=os" -e"GOARCH=arch" image go build -v -o outputname

并获得相同的错误,只有“无效”工作目录为"/go/src/goapp"

这是我的代码:

package main

import (
    "bytes"
    "flag"
    "fmt"
    "os"
    "os/exec"
    "runtime"
    "strings"
)

func constructCmd(volumeMap, workingDir, goos, goarch, output, image string) []string {
    finalCmd := append([]string{"run", "--rm"},
        fmt.Sprintf("-v='%s'", volumeMap),
        fmt.Sprintf("-w='%s'", workingDir),
        fmt.Sprintf("-e='%s'", goos),
        fmt.Sprintf("-e='%s'", goarch),
    )

    finalCmd = append(finalCmd, image, "go build -v")

    if output != "" {
        finalCmd = append(finalCmd, fmt.Sprintf("-o %s", output))
    }

    return finalCmd
}

func main() {
    // Parse flags
    osPtr := flag.String("os", "windows", "Target distribution")
    archPtr := flag.String("arch", "amd64", "Target distribution")
    outputPtr := flag.String("out", "", "Output file name")
    flag.Parse()

    fmt.Printf("Building for %s/%s:\n", *osPtr, *archPtr)

    goos := "GOOS=" + *osPtr
    goarch := "GOARCH=" + *archPtr

    pwd, _ := os.Getwd()
    if runtime.GOOS == "windows" {
        pwd = strings.Replace(pwd, "C", "c", 1)
        pwd = strings.Replace(pwd, "\\", "/", -1)
    }
    workingDir := pwd[strings.Index(pwd, "/go"):]
    volumeMap := fmt.Sprintf("%s:%s", pwd, workingDir)

    var image string
    if len(flag.Args()) == 0 {
        image = "golang"
    } else {
        image = flag.Args()[0]
    }

    execCmd := constructCmd(volumeMap, workingDir, goos, goarch, *outputPtr, image)

    cmd := exec.Command("docker", execCmd...)
    cmdOutput := &bytes.Buffer{}
    cmd.Stdout = cmdOutput
    cmd.Stderr = cmdOutput
    err := cmd.Run()
    if err != nil {
        os.Stderr.WriteString(err.Error())
    }
    fmt.Print(string(cmdOutput.Bytes()))
}

要注意,如果我直接运行此命令,它没有问题。没错。所以这不是一个泊坞问题,这是一个问题。什么可能导致此错误?

1 个答案:

答案 0 :(得分:2)

删除引用的引号。如the exec package's documentation中所述,Go的标准lib os / exec包不会调用shell来执行Cmd:

  

与"系统"不同。从C和其他语言调用库,os / exec包故意不调用系统shell,也不扩展任何glob模式或处理通常由shell完成的其他扩展,管道或重定向。包的行为更像C" exec"功能系列。

除非您在命令中调用shell,否则不会调用shell来处理和删除这些引号。

例如,这个:

"-v='%s'"

应该是这样的:

"-v=%s"

评论更新:OP还发现并修复了第二个问题:

"go build -v"

需要分成不同的参数:

"go", "build", "-v"