强制程序在重定向时刷新其标准输出

时间:2010-01-13 10:23:58

标签: c linux stdio fifo

我有一个封闭的源程序,可以将输出打印到标准输出。我需要解析输出。所以我将输出重定向到fifo(我可以在父进程中读取,分叉和执行二进制文件)使用dup2然后执行程序。问题是文件中的fprintf调用变为缓冲,因为它现在正在写入文件。

我尝试在调用exec之前在stdout上使用_IONBF调用setvbuf。但问题仍然存在。

为什么setvbuf对我的情况没有帮助?

如何强制输出刷新?

3 个答案:

答案 0 :(得分:6)

setvbuf()没有区别,因为它改变了C运行时库的一部分状态,而不是操作系统的一部分。当新进程开始运行时,它的C运行时库将被重新初始化(即如果它完全使用CRT!)

我听说过这种解决方法的唯一方法是以某种方式伪造终端进入该过程。这是因为大多数CRT库默认只执行行缓冲,如果他们认为它们连接到交互式终端(在Unix世界中:if isatty()在文件描述符上返回true),否则它们将缓冲在更大的块中(通常为8Kb左右)。

This utility看起来是一个非常好的起点。 (借用对Trick an application into thinking its stdin is interactive, not a pipe的评论,其中包含其他有用的信息。)

答案 1 :(得分:2)

我猜你的程序中有这样的东西(你可以为你的测试重现这个,我在这里称之为isatty

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

const char* m1 = "%d: %s a TTY\n";

void isTty(FILE* f) {
    int fno = fileno(f);
    printf(m1, fno, (isatty(fno)) ? "is" : "is NOT");
}

int main(int argc, char* argv[]) {
    isTty(stdin);
    isTty(stdout);
}

例如,如果你运行它

$ ./isatty
0: is a TTY
1: is a TTY

$ ./isatty > isatty.out
$ cat isatty.out 
0: is a TTY
1: is NOT a TTY

$ ./isatty > isatty.out < /dev/null
$ cat isatty.out 
0: is NOT a TTY
1: is NOT a TTY

现在,如果您创建expect脚本isatty.expect(如果未安装,则为您的发行版安装expect

#! /usr/bin/expect -f

spawn "./isatty"
expect

并运行它

$ ./isatty.expect 
spawn ./isatty
0: is a TTY
1: is a TTY

$ ./isatty.expect > isatty.out 
$ cat isatty.out 
spawn ./isatty
0: is a TTY
1: is a TTY

答案 2 :(得分:2)

unbuffer工具可以解决此问题:

它是expect-dev的一部分,可以使用

安装在ubuntu中
sudo apt-get install expect-dev

使用它类型:

unbuffer ls > log.txt