Charlie Parker
Charlie Parker

Reputation: 5221

Does os.exec from go (golang) not execute commands in $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

Upvotes: 1

Views: 13472

Answers (3)

Charlie Parker
Charlie Parker

Reputation: 5221

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

cmd := exec.Command("my command")
b, err := cmd.Output()
//fmt.Println("string(b):", string(b)) //<--inspecting stdout before throwing an error revealed that it *was* doing my command!
if err != nil {
    log.Fatal(err)
}
fmt.Println("string(b):", string(b)) //<-- wouldn'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()'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("echo", os.Getenv("PATH"))

Upvotes: 1

atrn
atrn

Reputation: 92

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("sh", "-c", "echo $PATH")

Upvotes: 6

OneOfOne
OneOfOne

Reputation: 99224

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"))

Or you could use os.ExpandEnv:

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

Upvotes: 5

Related Questions