从 c 程序和 shell 脚本流式传输 exec 命令输出时的令人困惑的行为

指挥官大写

我编写了一个测试程序来分析今天导致错误的一段代码的行为,以更好地了解其行为。相反的情况发生了。

这是测试程序。它应该执行一个测试命令并将命令输出流式传输到标准输出。

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

func main() {
    cmd1 := exec.Command("./testcommands/testcommand.sh")
    execCmd(cmd1)
    cmd2 := exec.Command("./testcommands/testcommand")
    execCmd(cmd2)
}

func execCmd(cmd *exec.Cmd) {
    stderr, _ := cmd.StderrPipe()
    stdout, _ := cmd.StdoutPipe()
    multi := io.MultiReader(stdout, stderr)
    scanner := bufio.NewScanner(multi)
    cmd.Start()
    for scanner.Scan() {
        m := scanner.Text()
        fmt.Println(m)
    }
    cmd.Wait()
}

调用的两个测试命令基本相同。一种是用bash实现的

#!/bin/bash

for i in `seq 1 10` ; do 
    echo "run $i"
    sleep 1
done

另一个在 C

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

int main() {
    int i;
    for (i=1; i<=10; i++) {
        printf("run %d\n", i);
        sleep(1);
    }
    return 0;
}

shell 脚本的输出确实被流式传输(每秒 1 行),但是 c 程序的输出仅在程序完全完成后才到达(10 秒后一次 10 行)。

这超出了我的脑海。我什至不确定这是否按预期工作,我只是遗漏了一些东西,或者我是否应该打开错误报告 - 如果是这样,我什至不确定它是用于 bash、golang 还是 c . 或者也许这是我不知道的一些 linux 事情。

某程序员哥们

stdoutprintf写入)连接到终端时,stdout将被行缓冲,并且输出将在每个换行符上刷新(实际写入)。

但是当stdout没有连接到终端时,例如它用于重定向或管道,那么它就会被完全缓冲。完全缓冲意味着仅当缓冲区变满(在您的小示例中不太可能)或显式刷新(例如使用fflush(stdout)时才会写入输出

Goexec功能可能做的是为程序输入和输出创建管道

为了解决您的问题,您的 C 程序需要fflush在每次printf调用调用:

printf("run %d\n", i);
fflush(stdout);

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章