【问题标题】:how to properly capture all stdout/stderr如何正确捕获所有标准输出/标准错误
【发布时间】:2016-07-06 16:59:17
【问题描述】:

我想捕获所有stdoutstderr 并保存到一个文件中

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

主包

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

我期望在使用前面的代码从 go 调用它时可以获得相同的输出,奇怪的是,如果我将命令更改为 idwhoami uname 我会这样做得到结果并可以打印,因此想知道可能出了什么问题。

有什么想法吗?

更新

发现我必须等待程序完成,如 cmets 中建议的那样才能获得输出,但如果我想实时获得输出,我该如何实现这一点,最好的方法是什么这样做,io.Copyos.Pipe 等等?

【问题讨论】:

  • 你真的等了 1000 秒让/tmp/stdout 完成吗?请注意,cmd.Wait() 将阻止您的程序,直到命令完成运行。
  • 尝试将os.Stdoutfmt.Fprintf 结合使用,以保持简单,但如果您想要更专业的解决方案,则不要使用已经建议的日志记录。
  • 你考虑过go run main.go &amp;&gt; out+err.txt吗?编辑 nvm 我没有意识到你是从 go 调用子进程

标签: go stdout stderr


【解决方案1】:

但如果我想实时获得输出

一种方法是将os.Stdout 附加到cmd.Stdout

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

err := oCmd.Run()

然后您可以使用 File 代替 f,_ := os.Create("file")

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

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

【讨论】:

  • 谢谢,但我想我需要使用 gorutines,如果我想处理而不需要等待,以防我想例如预解析输出而不是将其直接发送到文件,类似于记录器。
  • afaik,在 Go 中,您必须创建一个作家并做一个作家的作家。 cmd.Stdout->写入->解析器->写入->os.Stdout。关于 goroutines,只需执行 go func(done chan){}。对此有一些模式。
猜你喜欢
  • 2013-05-11
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 2018-11-25
  • 1970-01-01
相关资源
最近更新 更多