Golang 内建包-exec

1. wiki

命令执行库,包装了 os.StartProcess,方便处理标准输入和输出和处理 IO 管道。cmd 结构为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Cmd struct {  
Path string //运行命令的路径,绝对路径或者相对路径
Args []string //命令参数
Env []string //进程环境,如果环境为空,则使用当前进程的环境
Dir string //指定command的工作目录,如果dir为空,则在调用进程所在当前目录中运行
Stdin io.Reader //标准输入,如果其是 nil,进程从 null device 中读取(os.DevNull)
//stdin 也可以是一个文件,否则在运行过程中再开一个goroutine去读取标准输入
Stdout io.Writer //标准输出
Stderr io.Writer //错误输出,如果两者(Stdout和Stderr)为空,则运行时将响应的文件描述符连接到 os.DevNull
ExtraFiles []*os.File   
SysProcAttr *syscall.SysProcAttr
Process *os.Process //Process 是底层进程,只启动一次
ProcessState *os.ProcessState //ProcessState 包含一个退出进程的信息,当进程调用 Wait 或者 Run 时便会产生该信息
}

2. 使用

exec.Command() 函数返回一个 Cmd 对象

1. cmd.Run() 无返回结果

直接调用 Cmd 对象的 Run 函数,返回的只有成功和失败,获取不到任何输出的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import (
"log"
"os/exec"
)

func main() {
cmd := exec.Command("ls", "-l", "/var/log/")
err := cmd.Run()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
}

2. cmd.CombinedOutput() 有返回结果

调用 Cmd 的 CombinedOutput 函数,获取输出结果,但不区分 stdout 和 stderr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"fmt"
"log"
"os/exec"
)

func main() {
cmd := exec.Command("ls", "-l", "/var/log/")
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("combined out:\n%s\n", string(out))
log.Fatalf("cmd.Run() failed with %s\n", err)
}
fmt.Printf("combined out:\n%s\n", string(out))
}

3. 返回标准输出和错误输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"bytes"
"fmt"
"log"
"os/exec"
)

func main() {
cmd := exec.Command("ls", "-l", "/var/log/*.log")
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout // 标准输出
cmd.Stderr = &stderr // 标准错误
err := cmd.Run()
outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
fmt.Printf("out:\n%s\nerr:\n%s\n", outStr, errStr)
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
}

4. 管道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import (
"os"
"os/exec"
)
func main() {
c1 := exec.Command("grep", "ERROR", "/var/log/messages")
c2 := exec.Command("wc", "-l")
c2.Stdin, _ = c1.StdoutPipe()
c2.Stdout = os.Stdout
_ = c2.Start()
_ = c1.Run()
_ = c2.Wait()
}