【问题标题】:How to show output of command in stdout/stderr while also saving the output into a variable in Go?如何在 stdout/stderr 中显示命令输出,同时将输出保存到 Go 中的变量中?
【发布时间】:2020-08-15 13:38:37
【问题描述】:

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

    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.Copy 而不将其拆分为 goroutine。这将从 tee-reader 的tstdout 读取,直到 tee-reader 返回 EOF。 tee-reader 从管道的读取端r 读取。写端当前是打开的,没有要读取的字节,所以io.Copy 等待treader 的数据(或EOF)。没有其他任何东西提供任何数据,所以io.Copy 继续等待,就像 tee 阅读器一样,两者都将一直这样做,或者直到某个其他事件终止程序 - 没有其他人有 r,所以没有人在上面写还没有。
  • 如果你将两个 io.Copy 调用作为新的 goroutines 分离出来,你会得到更好的结果。

标签: go io pipe stdout stderr


【解决方案1】:

您需要从“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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-31
    • 2016-09-01
    • 2014-04-09
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    相关资源
    最近更新 更多