2010-01-13 52 views
9

我有一个封闭的源程序,将输出打印到标准输出。我需要解析输出。所以我使用dup2将输出重定向到一个fifo(我可以在父进程中读取它,并使用dup2来执行),然后执行程序。问题在于文件中的fprintf调用会被缓冲,因为它正在写入文件。强制程序在重定向时刷新其标准输出

我试着在调用exec之前在标准输出上用_IONBF调用setvbuf。但问题依然存在。

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

我该如何强制输出被刷新?

回答

5

setvbuf()没有什么区别,因为它改变了C运行时库的一部分的状态,而不是OS的一部分。当新进程开始运行时,它的C运行时库将被重新初始化(这就是说,如果它使用CRT的话)

我听说为解决这个问题的唯一方法是以某种方式假冒终端进程。这是因为如果大多数CRT库相信它们连接到交互式终端(默认情况下,在Unix世界中:如果isatty()在文件描述符上返回true),则缺省情况下它们将仅执行行缓冲,否则它们将缓冲在较大的块中(通常为8Kb或所以)。

This utility看起来像一个很好的开始。 (借用上Trick an application into thinking its stdin is interactive, not a pipe评论,其中有其他有用的信息。)

+0

我派生出来的过程,调用setvbuf用来在子进程,然后exec的是高层的另一个shell脚本,最后高管二进制的shell脚本。我可以更改最终的exec命令(bash),以便它以某种方式禁用缓冲。 – 2010-01-13 12:15:18

+1

我再说一遍,在execing之前调用setvbuf()是无用的 - 在exec()中保留了任何C运行时库状态都没有!你exec()的最后一个过程可能不会使用CRT! (不太可能,但可能。) – 2010-01-13 12:37:39

+0

好吧,我正在尝试pty方法 请参阅http://stackoverflow.com/questions/2056858/cannot-write-to-pty-linux – 2010-01-13 13:22:54

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 

现在,如果你创建一个脚本expectisatty.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

unbuffer工具可以帮助这个问题:

这是expect-dev的一部分,可以安装在使用

的ubuntu
sudo apt-get install expect-dev 

使用它输入:

unbuffer ls > log.txt