exec
最后更新于:2022-04-02 02:45:20
[TOC]
## 语法
```
type Cmd struct {
// 该字段不能为空,如为相对路径会相对于Dir字段。
Path string
// Args保管命令的参数,包括命令名作为第一个参数;如果为空切片或者nil,相当于无参数命令。
//
// 典型用法下,Path和Args都应被Command函数设定。
Args []string
// Env指定进程的环境,如为nil,则是在当前进程的环境下执行。
Env []string
// Dir指定命令的工作目录。如为空字符串,会在调用者的进程当前目录下执行。
Dir string
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
// ExtraFiles指定额外被新进程继承的已打开文件流,不包括标准输入、标准输出、标准错误输出。
// 如果本字段非nil,entry i会变成文件描述符3+i。
//
// BUG: 在OS X 10.6系统中,子进程可能会继承不期望的文件描述符。
// http://golang.org/issue/2603
ExtraFiles []*os.File
// SysProcAttr保管可选的、各操作系统特定的sys执行属性。
// Run方法会将它作为os.ProcAttr的Sys字段传递给os.StartProcess函数。
SysProcAttr *syscall.SysProcAttr
// Process是底层的,只执行一次的进程。
Process *os.Process
// ProcessState包含一个已经存在的进程的信息,只有在调用Wait或Run后才可用。
ProcessState *os.ProcessState
}
func (c *Cmd) StdinPipe() (io.WriteCloser, error)
func (c *Cmd) StdoutPipe() (io.ReadCloser, error)
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
func (c *Cmd) Run() error // 阻塞直到完成
func (c *Cmd) Start() error // 不会等待该命令完成即返回
func (c *Cmd) Wait() error
func (c *Cmd) Output() ([]byte, error)
func (c *Cmd) CombinedOutput() ([]byte, error)
```
## 实例
### LookPath 查看命令是否存在
```
path, err := exec.LookPath("ls")
if err != nil {
fmt.Printf("didn't find 'ls' executable\n")
} else {
fmt.Printf("'ls' executable is in '%s'\n", path)
}
```
### Stdin / Stdout 指定输入输出
实例1:通过 Stdin和Stdout 指定输入,输出
```
var out bytes.Buffer
// tr命令 小写转大写
cmd := exec.Command("tr", "a-z", "A-Z")
cmd.Stdin = strings.NewReader("some input")
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Printf("in all caps: %q\n", out.String())
// in all caps: "SOME INPUT"
```
### 设置环境变量
```
cmd := exec.Command("prog")
cmd.Env = append(os.Environ(),
"FOO=duplicate_value", // ignored
"FOO=actual_value", // this value is used
)
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
```
### Output 直接输出
```
out, err := exec.Command("date").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
```
### Start 需要 Wait
```
cmd := exec.Command("sleep", "5")
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
log.Printf("Waiting for command to finish...")
err = cmd.Wait()
log.Printf("Command finished with error: %v", err)
```
### CommandContext
```
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
if err := exec.CommandContext(ctx, "sleep", "5").Run(); err != nil {
// This will fail after 100 milliseconds. The 5 second sleep
// will be interrupted.
}
```
';