exec: executable file not found in $PATH

Mathieu Nls picture Mathieu Nls · Jun 27, 2017 · Viewed 24.5k times · Source

I am trying to send the HUP signal to tor in Go.

    command := exec.Command("pidof tor | xargs kill -HUP")
    command.Dir = "/bin"

    if cmdOut, err := command.CombinedOutput(); err != nil {
        log.Panic("There was an error running HUP ", string(cmdOut), err)
        panic(err)
    }

I've tried numerous version of this (with/out args, with/out the Dir, ...) and it always comes back with the same error:

2017/06/27 13:36:31 There was an error running HUP exec: "pidof tor | xargs kill -HUP": executable file not found in $PATH
panic: There was an error running HUP exec: "pidof tor | xargs kill -HUP": executable file not found in $PATH

goroutine 1 [running]:
panic(0x639ac0, 0xc42000d260)
        /usr/local/go/src/runtime/panic.go:500 +0x1a1
log.Panic(0xc420049f08, 0x3, 0x3)
        /usr/local/go/src/log/log.go:320 +0xc9
main.main()

Running the command from the console works perfectly:

root@c8927c4a456e:/go/src/github.com/project# pidof tor | xargs kill -HUP
Jun 27 13:40:07.000 [notice] Received reload signal (hup). Reloading config and resetting internal state.
Jun 27 13:40:07.000 [notice] Read configuration file "/etc/tor/torrc".

Here's my $PATH

root@c8927c4a456e:/go/src/github.com/project# echo $PATH
/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

I've done this previously with git command and it was working seamlessly. Am I missing something ?

Answer

Adrian picture Adrian · Jun 27, 2017

Per the documentation, the first argument passed to exec.Command is the name of an executable - that's it. It's not interpreted by the shell; it's the name of an executable you want to fork. If you need to pass in arguments, you can pass them in as additional parameters to Command, or you can pass them to the returned object afterward.

In your case, you're using two commands and piping the stdout of one to the stdin of another. You could do this in pure Go (piping the Stdout reader of one to the Stdin writer of the other), or you could rely on the shell to do it. In the latter case, your executable would be sh or bash, and the arguments would be ["-c", "pidof tor | xargs kill -HUP"]. For example:

cmd := exec.Command("bash", "-c", "pidof tor | xargs kill -HUP")