捕获exec.Command的缓冲stdout输出

时间:2018-12-18 11:11:46

标签: go buffer stdout

我正在尝试捕获外部程序的输出。示例:

#include <stdio.h>
#include <unistd.h>
#include <stddef.h>

int main() {

    int i = 0;

    while(i < 10) {
        printf("i = %i\n", i++);
        usleep(2000000);
    }
    return 0;
}

这是我的main.go:

package main

import (
    "bufio"
    "io"
    "log"
    "os/exec"
)

func reecho(closer io.ReadCloser)  {
    reader := bufio.NewReader(closer)

    for {
        s, e := reader.ReadString('\n')
        if e != nil {
            log.Println(e)
            break
        }
        log.Println(s)
    }
}

func main() {
    cmd := exec.Command("./infcount")
    log.Println("starting ", cmd)
    stdout, err := cmd.StdoutPipe()
    stderr, _ := cmd.StderrPipe()

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

    go reecho(stdout)
    go reecho(stderr)

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

问题是标准输出的缓冲。仅当stdout缓冲区或程序中的4096字节退出时,“ reecho”才获取数据(对于我的简短示例)。有没有办法减小缓冲区大小以捕获每一行输出?

更新:从shell运行时,相同的二进制“ infcount”可以正常工作。它将每个“ i”写入屏幕。

1 个答案:

答案 0 :(得分:0)

您的C程序的版本,该版本将在发生时跟踪输出

   #include <stdio.h>
    #include <unistd.h>
    #include <stddef.h>

    int main() {

        int i = 0;

        while(i < 10) {
            printf("i = %i\n", i++);
            usleep(2000000);
            fflush(stdout);
        }
        return 0;
    }

如果它是现有的预编译程序,那么stdbuf可以对其进行修复,请参见https://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html