我有一个封闭的源程序,将输出打印到标准输出。我需要解析输出。所以我使用dup2将输出重定向到一个fifo(我可以在父进程中读取它,并使用dup2来执行),然后执行程序。问题在于文件中的fprintf调用会被缓冲,因为它正在写入文件。强制程序在重定向时刷新其标准输出
我试着在调用exec之前在标准输出上用_IONBF调用setvbuf。但问题依然存在。
为什么setvbuf在我的情况下没有帮助?
我该如何强制输出被刷新?
我有一个封闭的源程序,将输出打印到标准输出。我需要解析输出。所以我使用dup2将输出重定向到一个fifo(我可以在父进程中读取它,并使用dup2来执行),然后执行程序。问题在于文件中的fprintf调用会被缓冲,因为它正在写入文件。强制程序在重定向时刷新其标准输出
我试着在调用exec之前在标准输出上用_IONBF调用setvbuf。但问题依然存在。
为什么setvbuf在我的情况下没有帮助?
我该如何强制输出被刷新?
setvbuf()
没有什么区别,因为它改变了C运行时库的一部分的状态,而不是OS的一部分。当新进程开始运行时,它的C运行时库将被重新初始化(这就是说,如果它使用CRT的话)
我听说为解决这个问题的唯一方法是以某种方式假冒终端进程。这是因为如果大多数CRT库相信它们连接到交互式终端(默认情况下,在Unix世界中:如果isatty()
在文件描述符上返回true),则缺省情况下它们将仅执行行缓冲,否则它们将缓冲在较大的块中(通常为8Kb或所以)。
This utility看起来像一个很好的开始。 (借用上Trick an application into thinking its stdin is interactive, not a pipe评论,其中有其他有用的信息。)
我想你有这样的事情在你的程序(可以重现这个对于你的测试,我叫它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
的unbuffer
工具可以帮助这个问题:
这是expect-dev
的一部分,可以安装在使用
sudo apt-get install expect-dev
使用它输入:
unbuffer ls > log.txt
我派生出来的过程,调用setvbuf用来在子进程,然后exec的是高层的另一个shell脚本,最后高管二进制的shell脚本。我可以更改最终的exec命令(bash),以便它以某种方式禁用缓冲。 – 2010-01-13 12:15:18
我再说一遍,在execing之前调用setvbuf()是无用的 - 在exec()中保留了任何C运行时库状态都没有!你exec()的最后一个过程可能不会使用CRT! (不太可能,但可能。) – 2010-01-13 12:37:39
好吧,我正在尝试pty方法 请参阅http://stackoverflow.com/questions/2056858/cannot-write-to-pty-linux – 2010-01-13 13:22:54