Go 如何正确捕获所有stdout/stderr
我想捕获所有数据并保存到文件中 出于测试目的,我仅打印使用以下方法捕获的内容: 包干管Go 如何正确捕获所有stdout/stderr,go,stdout,stderr,Go,Stdout,Stderr,我想捕获所有数据并保存到文件中 出于测试目的,我仅打印使用以下方法捕获的内容: 包干管 import ( "bufio" "bytes" "fmt" "io" "os/exec" ) func main() { cmd := exec.Command("/tmp/stdout") stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) cmd.Stdout = st
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命令:
主程序包
进口(
“fmt”
“操作系统”
“时间”
)
func main(){
对于i:=1;i<1000;i++{
如果i%3==0{
fmt.Fprintf(os.Stderr,“Stderr i:%d\n”,i)
}否则{
fmt.Printf(“标准输出i:%d\n”,i)
}
时间。睡眠(1*时间。秒)
}
}
由于某些原因,我无法从输出中捕获任何内容,如果我运行/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调用时可以获得相同的输出,奇怪的是,如果我将命令更改为类似于id
,whoami
uname
的内容,我确实得到了结果,并且可以打印出来,因此想知道可能出了什么问题
有什么想法吗
更新
发现我必须按照注释中的建议等待程序完成才能获得输出,但如果我想实时获得输出,如何实现这一点,最好的方法是什么,或者io.Copy
anos.Pipe
,等等
但如果我想得到实时输出
一种方法是将os.Stdout
附加到cmd.Stdout
oCmd := exec.Command(bin, cmdArgs...)
oCmd.Stdout = os.Stdout
oCmd.Stderr = os.Stderr
err := oCmd.Run()
然后您可以将文件改为使用f,:=os.Create(“文件”)
如果您想同时将其写入文件和终端,我怀疑(我还没有这样做),您需要使用io.multiwriters
f, _ := os.Create("file")
cmd.Stdout = io.MultiWriter(os.Stdout, f)
您是否真的等了1000秒才完成
/tmp/stdout
?请注意,cmd.Wait()
将阻止您的程序,直到命令完成运行。请尝试使用go日志记录,尝试将os.Stdout
与fmt.Fprintf
组合,以保持简单,但如果您想要更专业的解决方案,您是否考虑过go run main.go&>out+err.txt
?编辑nvm我没有意识到您正在从goThanks调用子进程,但我认为我需要使用gorutines,如果我想处理而不需要等待,例如,我想预解析输出,而不是直接将其发送到文件,如go中的logger.afaik,你必须创造一个作家,做一个作家中的作家。cmd.Stdout->write->parser->write->os.Stdout。关于goroutines,只需执行一个go func(done chan){}
。这有一些模式。