Как показать вывод команды в stdout / stderr, сохраняя при этом вывод в переменную в Go? - PullRequest
0 голосов
/ 01 мая 2020

Я думаю, что я на правильном пути, но мое решение просто зависает и ничего не выводит на экран, что я тут не так делаю?

    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(),
    }

1 Ответ

0 голосов
/ 01 мая 2020

Вам нужно читать из читателя, возвращенного из "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

И программа должна завершиться и успешно завершиться .

...