subhash kumar singh
subhash kumar singh

Reputation: 2756

Not able to execute go file using os/exec package

I am following the golang tutorial for writing my web app. I am modifying the code from tutorial page, so that I can execute the saved page as go code (similar to go playground). But when I try to execute the saved go file using the os/exec package, it throws the following error.

exec: "go run testcode.go": executable file not found in $PATH

Following is my modified code :

// Structure to hold the Page
type Page struct {
    Title  string
    Body   []byte
    Output []byte
}

// saving the page
func (p *Page) save() { // difference between func (p *Page) and func (p Page)
    filename := p.Title + ".go"
    ioutil.WriteFile(filename, p.Body, 0777)
}

// handle for the editing
func editHandler(w http.ResponseWriter, r *http.Request) {
    title := r.URL.Path[len("/edit/"):]

    p, err := loadPage(title)

    if err != nil {
        p = &Page{Title: title}
    }
    htmlTemp, _ := template.ParseFiles("edit.html")
    htmlTemp.Execute(w, p)
}

// saving the page
func saveHandler(w http.ResponseWriter, r *http.Request) {
    title := r.URL.Path[len("/save/"):]
    body := r.FormValue("body")

    p := Page{Title: title, Body: []byte(body)}
    p.save()

    http.Redirect(w, r, "/exec/"+title, http.StatusFound) // what is statusfound
}

// this function will execute the code.
func executeCode(w http.ResponseWriter, r *http.Request) {

    title := r.URL.Path[len("/exec/"):]

    cmd := "go run " + title + ".go"
    //cmd = "go"
    fmt.Print(cmd)
    out, err := exec.Command(cmd).Output()

    if err != nil {
        fmt.Print("could not execute")
        fmt.Fprint(w, err)
    } else {
        p := Page{Title: title, Output: out}

        htmlTemp, _ := template.ParseFiles("output.html")
        htmlTemp.Execute(w, p)
    }
}

Please tell me why I am not able to able to execute the go file.

Upvotes: 4

Views: 20338

Answers (2)

DavidGamba
DavidGamba

Reputation: 3613

The accepted answer states that the first argument to os.exec.Command is the full path to the executable. From the docs:

"If name contains no path separators, Command uses LookPath to resolve the path to a complete name if possible. Otherwise it uses name directly".

What you should do to avoid executable file not found in $PATH errors, besides passing the arguments after the executable name as suggested before, is to set your PATH either in your SHELL or using os.Setenv. If you hardcode the full location of the command like indicated, your program might not be portable to another Unix OS.

For example, the command lspci is located under /usr/bin in ubuntu and under /sbin/ in RHEL. If you do this:

os.Setenv("PATH", "/usr/bin:/sbin")
exec.Command("lspci", "-mm")

Then your program will excecute in both ubuntu and RHEL.

Or, form the shell, you can also do: PATH=/sbin; my_program

NOTE: The commands above are limiting the PATH to the explicitly indicated paths. If you want to add to the existing path in the shell for example, do PATH=/sbin:$PATH; my_program; In go you can probably read the variable with os.Getenv and then append to that when doing os.Setenv.

Upvotes: 1

fabmilo
fabmilo

Reputation: 48310

You are invoking command in the wrong way. The first string is the full path to the executable

os.exec.Command:func Command(name string, arg ...string)

so you want exec.Command("/usr/bin/go", "run", title+".go")

Upvotes: 16

Related Questions