os/exec包装了os.StartProcess方法,更方便的进行输入和输出的访问,提供I/O pipe等功能。
调用Command方法,你需要传入要执行的程序和参数,它会返回一个*Cmd的数据结构,主要调用它的Run、Output、CombinedOutput方法。之后这个对象就不能重用了。
执行命令并等待
cmd := exec.Command("ls", "-lah")
err := cmd.Run()
if err != nil {
log.Fatalf("failed to call cmd.Run(): %v", err)
}
Run
方法会执行外部命令并等待命令完成。如果命令正常执行,没有错误,返回码为0,那么Run返回的err == nil,那么返回一个*ExitError,有时候你需要读取cmd.Stdout甚至cmd.Stderr以便获取详细的错误信息。
执行命令不等待
cmd := exec.Command("ls", "-lah")
err := cmd.Start()
if err != nil {
log.Fatalf("failed to call cmd.Start(): %v", err)
}
如果你不想等待执行结果,可以调用Start
方法。
如果Start成功,Process和ProcessState字段会被设置。你可以检查ProcessState.Exited()判断程序是否退出。如果你想再阻塞等待程序的完成,你可以调用Wait方法。
事实上,Run方法就是利用Start方法和Wait方法实现的:
func (c *Cmd) Run() error {
if err := c.Start(); err != nil {
return err
}
return c.Wait()
}
添加环境变量
cmd := exec.Command("bash", "-c", "echo $myvar")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
// cmd.Env = os.Environ()
cmd.Env = []string{"myvar=abc"}
err := cmd.Run()
if err != nil {
log.Fatalf("failed to call cmd.Run(): %v", err)
}
指定工作路径
默认情况下进程的工作路径是调用这个进程的文件夹,但也可以手工指定 os/exec
的 Cmd.Dir
cmd := exec.Command("ls", "-lah")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = "/"
cmd.Run()
可执行程序Path
Cmd.Path是要执行的程序的路径. 如果是相对路径,那么它基于Cmd.Dir计算相对路径。如果程序已经在系统$PATH路径下,那么可以直接写程序名。
cmd := exec.Command("go", "env")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Printf("path: %s", cmd.Path)
cmd.Run()
go os/exec 简明教程 https://colobu.com/2020/12/27/go-with-os-exec/