go - 如何在stdout/stderr中显示命令输出,同时还将输出保存到Go中的变量中?

标签 go io pipe stdout stderr

我认为我走在正确的轨道上,但是我的解决方案只是挂起并且无法在屏幕上打印任何内容,这是我在做什么错?

    r, w := io.Pipe()
    var stdout, stderr bytes.Buffer
    cmd.Stdout = w
    cmd.Stderr = &stderr
    tstdout := io.TeeReader(r, os.Stdout)
    tstderr := io.TeeReader(r, os.Stderr)
    io.Copy(&stdout, tstdout)
    io.Copy(&stderr, tstderr)

    err := cmd.Run()

    res := processResult{
        stderr.String(),
        stdout.Bytes(),
    }

最佳答案

您需要异步读取从“io.TeeReader”返回的阅读器。这是一个与我认为您尝试执行的操作类似的示例。

package main

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

func main() {
    prout, pwout := io.Pipe()
    prerr, pwerr := io.Pipe()

    cmd := exec.Command("sh", "-c", "echo this is stdout; echo 1>&2 this is stderr")
    cmd.Stdout = pwout
    cmd.Stderr = pwerr

    tout := io.TeeReader(prout, os.Stdout)
    terr := io.TeeReader(prerr, os.Stderr)

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

    var bout, berr bytes.Buffer

    go func() {
        if _, err := io.Copy(&bout, tout); err != nil {
            log.Fatal(err)
        }
    }()

    go func() {
        if _, err := io.Copy(&berr, terr); err != nil {
            log.Fatal(err)
        }
    }()

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

    fmt.Printf("buffered out %s", bout.String())
    fmt.Printf("buffered err %s", berr.String())
}

输出为:
this is stdout
this is stderr
buffered out this is stdout
buffered err this is stderr

并且该程序应运行完成并成功退出。

关于go - 如何在stdout/stderr中显示命令输出,同时还将输出保存到Go中的变量中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61536139/

相关文章:

go - go中一个 channel 使用两个箭头写入另一个 channel 是什么意思

google-app-engine - 使用 Go 的 App Engine 上的静态文件托管限制

file - 使用 buffo.read 读取文件时 Golang 动态调整 slice 大小

python - `format()` 和 `str()` 之间有什么区别?

linux - 重定向与管道 - 为什么它有效以及为什么它无效

go - 如何在 Go 中获取指向 Interface{} 的底层值的指针

hadoop - 在 Windows 7 上构建 Hadoop

java - 写入文件但仅保存最后一行

linux - strace 上的 grep 仅使用 stderr 到 stdout

c - 通过 C 中的中心函数管理管道