在线文档  >   Golang练习   >   生成进程

有时,我们的Go程序需要启动其他非Go的进程。

package main

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

func main() {

    // 我们从一个简单的命令开始,它不需要任何参数或输入,只是将一些信息打印到标准输出。
    // `exec.Command`函数创建了一个对象来代表该外部进程。
    dateCmd := exec.Command("date")

    // `Output`方法运行命令,等待其完成并收集其标准输出。
    // 如果没有错误,`dateOut`将包含日期信息的字节。
    dateOut, err := dateCmd.Output()
    if err != nil {
        panic(err)
    }
    fmt.Println("> date")
    fmt.Println(string(dateOut))

    // `Command`和`*exec.Error`和`*exec.ExitError`方法将返回`*exec.Error`,如果执行命令时出现问题(例如路径错误),
    // 并且`*exec.ExitError`如果命令成功运行但退出代码为非零,则会出现此错误返回值。
    _, err = exec.Command("date", "-x").Output()
    if err != nil {
        switch e := err.(type) {
        case *exec.Error:
            fmt.Println("failed executing:", err)
        case *exec.ExitError:
            fmt.Println("command exit rc =", e.ExitCode())
        default:
            panic(err)
        }
    }

    // 接下来,我们将查看稍微复杂一些的情况,其中我们将数据从`stdin`管道传输到外部进程,并从其`stdout`中收集结果。
    grepCmd := exec.Command("grep", "hello")

    // 在此,我们显式地获取了输入/输出管道,启动了该进程,向其中写入一些输入,读取结果的输出,最后等待该进程退出。
    grepIn, _ := grepCmd.StdinPipe()
    grepOut, _ := grepCmd.StdoutPipe()
    grepCmd.Start()
    grepIn.Write([]byte("hello grep\ngoodbye grep"))
    grepIn.Close()
    grepBytes, _ := io.ReadAll(grepOut)
    grepCmd.Wait()

    // 我们在上面的示例中省略了错误检查,但您可以使用所有这些的通常`if err != nil`模式进行错误检查。
    // 我们也只收集了`StdoutPipe`的结果,但您可以以完全相同的方式收集`StderrPipe`。
    fmt.Println("> grep hello")
    fmt.Println(string(grepBytes))

    // 请注意,当启动命令时,我们需要提供明确定义的命令和参数数组,而不是仅仅传递一个命令行字符串。
    // 如果您想要启动一个带有字符串的完整命令,可以使用`bash`的`-c`选项:
    lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
    lsOut, err := lsCmd.Output()
    if err != nil {
        panic(err)
    }
    fmt.Println("> ls -a -l -h")
    fmt.Println(string(lsOut))
}

运行结果如下:

# 生成的程序返回的输出,和我们直接通过命令行运行这些程序的输出是相同的。
$ go run spawning-processes.go 
> date
Thu 05 May 2022 10:10:12 PM PDT

# date 没有“-x”标志,因此它将退出并显示错误消息和非零返回代码。
command exited with rc = 1
> grep hello
hello grep

> ls -a -l -h
drwxr-xr-x  4 mark 136B Oct 3 16:29 .
drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
-rw-r--r--  1 mark 1.3K Oct 3 16:28 spawning-processes.go