无法使用os/exec包执行go文件。

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

Not able to execute go file using os/exec package

问题

我正在遵循golang教程编写我的Web应用程序。我正在修改来自教程页面的代码,以便我可以将保存的页面作为go代码执行(类似于go playground)。但是,当我尝试使用os/exec包执行保存的go文件时,它会抛出以下错误。

> exec: "go run testcode.go": 在$PATH中找不到可执行文件

以下是我修改后的代码:

// 保存页面的结构体
type Page struct {
	Title  string
	Body   []byte
	Output []byte
}

// 保存页面
func (p *Page) save() { // func (p *Page)和func (p Page)之间的区别
	filename := p.Title + ".go"
	ioutil.WriteFile(filename, p.Body, 0777)
}

// 编辑处理函数
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)
}

// 保存处理函数
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) // StatusFound是什么意思
}

// 执行代码的函数
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("无法执行")
		fmt.Fprint(w, err)
	} else {
		p := Page{Title: title, Output: out}

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

请告诉我为什么我无法执行go文件。

英文:

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.

答案1

得分: 16

你正在错误地调用命令。第一个字符串应该是可执行文件的完整路径。

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

所以你应该使用 exec.Command("/usr/bin/go", "run", title+".go")

英文:

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

答案2

得分: 1

接受的答案指出,os.exec.Command的第一个参数是可执行文件的完整路径。根据文档:

“如果name不包含路径分隔符,Command会使用LookPath来解析路径以获取完整的name。否则,它直接使用name”。

为了避免“在$PATH中找不到可执行文件”的错误,除了按照之前建议的在可执行文件名后传递参数之外,你还应该在SHELL中设置你的PATH,或者使用os.Setenv。如果像指示的那样硬编码命令的完整位置,你的程序可能无法在另一个Unix操作系统上运行。

例如,命令lspci在Ubuntu下位于/usr/bin目录下,在RHEL下位于/sbin/目录下。如果你这样做:

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

那么你的程序将在Ubuntu和RHEL上都执行。

或者,从shell中,你也可以这样做:PATH=/sbin; my_program

注意:上述命令将PATH限制为显式指定的路径。如果你想在shell中添加到现有的路径中,可以使用PATH=/sbin:$PATH; my_program;在Go中,你可以使用os.Getenv读取变量,然后在执行os.Setenv时追加到该变量中。

英文:

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.

huangapple
  • 本文由 发表于 2014年12月13日 04:34:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/27451697.html
匿名

发表评论

匿名网友

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

确定