如何正确捕获所有stdout / stderr

时间:2016-07-06 16:59:18

标签: go stdout stderr

我想捕获所有stdoutstderr

并将其保存到文件中

出于测试目的,我只打印使用此功能捕获的内容:

package main

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

func main() {
    cmd := exec.Command("/tmp/stdout")
    stdout := new(bytes.Buffer)
    stderr := new(bytes.Buffer)

    cmd.Stdout = stdout
    cmd.Stderr = stderr

    if err := cmd.Start(); err != nil {
        panic(err)
    }

    if err := cmd.Wait(); err != nil {
        panic(err)
    }

    in := bufio.NewScanner(io.MultiReader(stdout, stderr))
    for in.Scan() {
        fmt.Println(in.Text())
    }

}

可以使用以下代码构建 / tmp / stdout 命令:

package main

import (
    "fmt"
    "os"
    "time"
)

func main() {

    for i := 1; i < 1000; i++ {
        if i%3 == 0 {
            fmt.Fprintf(os.Stderr, "STDERR i: %d\n", i)
        } else {
            fmt.Printf("STDOUT i: %d\n", i)
        }
        time.Sleep(1 * time.Second)
    }

}

由于某些原因,我无法从输出中捕获任何内容,如果我运行/tmp/stdout命令,我得到了这个:

$ /tmp/stdout 
STDOUT i: 1
STDOUT i: 2
STDERR i: 3
STDOUT i: 4
STDOUT i: 5
STDERR i: 6
STDOUT i: 7

我希望在使用之前的代码调用它时可以获得相同的输出,奇怪的是如果我将命令更改为idwhoami { {1}}我确实得到了结果并且可以打印,因此想知道可能出现的问题。

有什么想法吗?

更新

发现我必须等待程序完成,正如评论中建议的那样才能获得输出,但是如果我想实时获得输出我怎么能实现这一点,那可能是最好的方法这样做,unameio.Copy等等?

1 个答案:

答案 0 :(得分:2)

  

但是如果我想实时获得输出

这样做的一种方法是将os.Stdout附加到cmd.Stdout

oCmd := exec.Command(bin, cmdArgs...)
oCmd.Stdout = os.Stdout
oCmd.Stderr = os.Stderr

err := oCmd.Run()

然后,您可以使用f,_ := os.Create("file")来使用文件。

如果你想同时将它写入文件和终端,我怀疑(我还没有这样做),你需要使用io.Mutiwriters

f, _ := os.Create("file")
cmd.Stdout = io.MultiWriter(os.Stdout, f)