我正在编写一个非常简单的脚本,它只是通过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()))
}
要注意,如果我直接运行此命令,它没有问题。没错。所以这不是一个泊坞问题,这是一个问题。什么可能导致此错误?
答案 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"