Поймать буферизованный вывод stdout exec.Command - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь отловить вывод внешней программы.Пример:

#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)
    }
}

Проблема в буферизации стандартного вывода.«reecho» получает данные, только когда 4096 байт в буфере stdout или программе завершается (для моего короткого примера)Есть ли способ уменьшить размер буфера для перехвата каждой строки вывода?

Обновление: тот же двоичный файл 'infcount' отлично работает при запуске из оболочки.Он выводит каждое «я» на экран.

1 Ответ

0 голосов
/ 18 декабря 2018

версия вашей 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

...