Go - 组合cmd.StdoutPipe和Cmd.StderrPipe

zso*_*t.k 4 exec go

我想在Go中执行一个命令,并将其stdout和stderr组合成一个流.我写了这段代码,它只读取了stdout,但我不知道如何将它与stderr结合起来:

package main

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

func runCommand() {
    var (
        err error
    )

    cmdName := "docker"
    cmdArgs := []string{"build", "--no-cache=true", "--force-rm=true", "."}

    cmd := exec.Command(cmdName, cmdArgs...)

    cmdReader, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Fprintln(os.Stderr, "Error creating StdoutPipe for Cmd", err)
    }

    scanner := bufio.NewScanner(cmdReader)
    go func() {
        for scanner.Scan() {
            fmt.Printf("docker build out | %s\n", scanner.Text())
        }
    }()

    err = cmd.Start()
    if err != nil {
        fmt.Fprintln(os.Stderr, "Error starting Cmd", err)
    }

    err = cmd.Wait()
    if err != nil {
        fmt.Fprintln(os.Stderr, "Error waiting for Cmd", err)
    }
}

func main() {
    runCommand()
}
Run Code Online (Sandbox Code Playgroud)

谢谢你的回答!

Cer*_*món 10

要将stdout和stderr组合到单个读取器,请将单个管道分配给Command.Stdout和Command.Stderr:

cmdReader, err := cmd.StdoutPipe()
cmd.Stderr = cmd.Stdout
Run Code Online (Sandbox Code Playgroud)

  • @kostix StdoutPipe 方法更容易使用,因为它[安排在 Start() 处关闭 os.Pipe writer 并在 Wait() 处关闭 os.Pipe reader](https://github.com/golang/go/blob/ 13f74db304fdf6dc6241485d6e6f3f6a0327633c/src/os/exec/exec.go#L512-L518)。 (2认同)

cd1*_*cd1 0

使用该函数io.MultiReader将多个阅读器合并为一个:

outReader, err := cmd.StdoutReader()
if err != nil {
    // handle err
}

errReader, err := cmd.StderrReader()
if err != nil {
    // handle err
}

cmdReader := io.MultiReader(outReader, errReader)
Run Code Online (Sandbox Code Playgroud)

  • 此方法先从 stdout 返回所有输出,然后再从 stdin 返回任何输出。 (5认同)