同时扫描 stdout 和 stderr

Mic*_*ael 6 stdout exec go stderr

我正在寻找一种将标准输出和标准错误作为一个流同时处理的方法。对于标准输出我可以使用:

cmd := exec.Command(command, flags...)
var wg sync.WaitGroup

stdout, err := cmd.StdoutPipe()
if err != nil {
    return fmt.Errorf("RunCommand: cmd.StdoutPipe(): %v", err)
}

if err := cmd.Start(); err != nil {
    return fmt.Errorf("RunCommand: cmd.Start(): %v", err)
}

scanner := bufio.NewScanner(stdout)
scanner.Split(ScanLinesR)
wg.Add(1)
go func() {
    for scanner.Scan() {
        text := scanner.Text()
        if strings.TrimSpace(text) != "" {
            DoWhateverYouNeedWithText(text)
        }
    }
    wg.Done()
}()

wg.Wait()
Run Code Online (Sandbox Code Playgroud)

但是如何将 stderr 添加到相同的代码中?

Mic*_*ael 3

正如上面评论者建议的那样,我添加了 2 个 goroutine(一个用于 stderr,一个用于关闭通道)。

var wg sync.WaitGroup

stdout, err := cmd.StdoutPipe()
if err != nil {
    return fmt.Errorf("RunCommand: cmd.StdoutPipe(): %v", err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
    return fmt.Errorf("RunCommand: cmd.StderrPipe(): %v", err)
}

if err := cmd.Start(); err != nil {
    return fmt.Errorf("RunCommand: cmd.Start(): %v", err)
}

outch := make(chan string, 10)

scannerStdout := bufio.NewScanner(stdout)
scannerStdout.Split(ScanLinesR)
wg.Add(1)
go func() {
    for scannerStdout.Scan() {
        text := scannerStdout.Text()
        if strings.TrimSpace(text) != "" {
            outch <- text
        }
    }
    wg.Done()
}()
scannerStderr := bufio.NewScanner(stderr)
scannerStderr.Split(ScanLinesR)
wg.Add(1)
go func() {
    for scannerStderr.Scan() {
        text := scannerStderr.Text()
        if strings.TrimSpace(text) != "" {
            outch <- text
        }
    }
    wg.Done()
}()

go func() {
    wg.Wait()
    close(outch)
}()

for t := range outch {
    DoWhateverYouNeedWithText(t)
}
Run Code Online (Sandbox Code Playgroud)