go(golang)中的os.exec命令是否不在$PATH中执行命令?

huangapple go评论67阅读模式
英文:

Does os.exec from go (golang) not execute commands in $PATH?

问题

我正在尝试使用Go(golang)的exec库执行shell命令。然而,每当我尝试使用go install安装的二进制文件来执行时,它都不起作用。

我尝试在终端上直接运行我的二进制文件,它们可以正常工作。我检查了我的$PATH是否包含了我的go路径下的bin文件,所以在终端上是正常的。但是当我尝试在os exec中进行相同的检查时,代码如下:

echo := exec.Command("echo", "$PATH")
b, err := echo.Output()
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(b))

但令人惊讶的是,它以一种奇怪的方式工作,它输出了字面字符串$PATH!!真是难以置信!我是不是做错了什么?我甚至无法看到os exec实际运行的$PATH...也无法像这样在go exec中运行我的二进制文件作为命令:

exec.Command("myCommand").Run()

有人对为什么会出现这种情况有任何建议吗?

这个问题的关键不在于打印$PATH。问题在于我无法运行安装在$GOPATH/bin下的命令,尽管它在$PATH下。

英文:

I was trying to execute shell commands using the exec library for go (golang). However, I whenever I tried to execute it using binaries that I installed with go install it didn't work.

I tried running my binaries just on the terminal and they work. I checked that my $PATH did have the bin file for my go path so thats good in the terminal. But then I tried to do that same check in os exec by doing:

echo := exec.Command("echo", "$PATH")
b, err := echo.Output()
if err != nil {
	log.Fatal(err)
}
fmt.Println(string(b))

But suprisingly, it works in a weird way, it echos the literal string $PATH!! Incredible! Is there something that I am doing wrong? I can't even see what $PATH os exec is actually running...nor can I run my binaries in go exec as commands as in:

exec.Command("myCommand").Run()

Anyone has any suggestions as to why this might be?

The issue with this question is not printing $PATH. What isn't working is that I can't run commands installed under $GOPATH/bin even though its under $PATH

答案1

得分: 5

环境变量扩展是一种Shell功能,而不是程序功能。

你需要使用os.Getenv("PATH")

echo := exec.Command("echo", os.Getenv("PATH"))

或者你可以使用os.ExpandEnv

echo := exec.Command(strings.Fields(os.ExpandEnv("echo $PATH"))...)

英文:

Environment variable expansion is a shell feature, not a program feature.

You will have to use os.Getenv("PATH").

echo := exec.Command("echo", os.Getenv("PATH"))

<strike>Or you could use os.ExpandEnv:

echo := exec.Command(strings.Fields(os.ExpandEnv(&quot;echo $PATH&quot;))...)

</strike>

答案2

得分: 5

你正在尝试运行一个shell命令echo $PATH,但没有使用shell进行变量展开。正在运行的echo是一个二进制文件,可能是/bin/echo,并且它被传递了字符串$PATH。由于这是shell的功能,并且它没有参与进来,所以不会进行展开。要获得你期望的结果,你需要使用shell来运行命令,例如exec.Command("sh", "-c", "echo $PATH")

英文:

You're trying to run a shell command, echo $PATH without using a shell to do the variable expansion. The echo being run is a binary, probably /bin/echo, and it is being passed the string $PATH. $PATH doesn't expand since that's a function of the shell and it's not involved so no expansion occurs. To get what you expected you need to use the shell to run the command, e.g. exec.Command(&quot;sh&quot;, &quot;-c&quot;, &quot;echo $PATH&quot;)

答案3

得分: 1

所以我找到了为什么无法运行我的命令的原因。这是我的原始代码:

cmd := exec.Command("my command")
b, err := cmd.Output()
//fmt.Println("string(b):", string(b)) //<--在抛出错误之前检查stdout,发现它确实执行了我的命令!
if err != nil {
    log.Fatal(err)
}
fmt.Println("string(b):", string(b)) //<--无法运行,所以我永远看不到它的输出。

它确实执行了命令,但由于我创建的命令返回了错误,所以exec也返回了错误,我无法确定它是因为找不到命令还是因为我的命令有问题而退出。因此,如果命令抛出错误但同时写入stdout,你可以在.Output()的返回值中获得“有效”的信息。

我尝试打印$PATH的唯一原因是为了查看我的命令是否在go的exec环境的$PATH中。但正如OneOfOne的答案明确指出的那样,可以通过以下方式找到它:

echo := exec.Command("echo", os.Getenv("PATH"))
英文:

So I figured it out why I wasn't able to run my command. This was my original code:

cmd := exec.Command(&quot;my command&quot;)
b, err := cmd.Output()
//fmt.Println(&quot;string(b):&quot;, string(b)) //&lt;--inspecting stdout before throwing an error revealed that it *was* doing my command!
if err != nil {
	log.Fatal(err)
}
fmt.Println(&quot;string(b):&quot;, string(b)) //&lt;-- wouldn&#39;t run so I would never see its out put.

It was running the command, but because the command I made was returning an error, so was exec and I couldn't tell if it was exiting because it wasn't finding the command or because my command was buggy. So if the command throws an error but also writes to stdout, you can have "valid" information on both of .Output()&#39;s return value.

The only reason I was trying to print $PATH was to see if my command was even in $PATH for go's exec env. But was OneOfOne's answer clearly states, it can be found by:

echo := exec.Command(&quot;echo&quot;, os.Getenv(&quot;PATH&quot;))

huangapple
  • 本文由 发表于 2014年8月8日 02:54:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/25190033.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定