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

发布于 2024-08-17 12:18:18 字数 240 浏览 10 评论 0原文

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

在调用 exec 之前,我尝试在标准输出上使用 _IONBF 调用 setvbuf 。但问题仍然存在。

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

我怎样才能强制刷新输出?

i have a closed source program that prints output to standard output. i need to parse the output. so i redirect the output to a fifo (from which i can read in the parent process that forks and execs the binary) using dup2 and then exec the program. the problem is that the fprintf calls in the file become buffered because it is now writing to a file.

i tried calling setvbuf with _IONBF on stdout before calling exec. but the problem still exists.

why does setvbuf not help in my case?

how can i force the output to get flushed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

十二 2024-08-24 12:18:18

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

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

这个实用程序看起来是一个非常好的起点。 (借用的评论应用程序认为它的标准输入是交互式的,而不是管道,管道还有其他有用的信息。)

setvbuf() makes no difference because it changes the state of part of the C runtime library, not part of the OS. When the new process begins running, its C runtime library will be reinitialised (that's if it uses a CRT at all!)

The only way I have heard of for getting around this is to somehow fake a terminal to the process. That's because most CRT libraries will by default perform only line buffering if they believe they are attached to an interactive terminal (in the Unix world: if isatty() returns true on the file descriptor), whereas otherwise they will buffer in larger blocks (typically 8Kb or so).

This utility looks like a pretty good place to start. (Borrowed from a comment on Trick an application into thinking its stdin is interactive, not a pipe, which has other useful info.)

我很OK 2024-08-24 12:18:18

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

安装在 ubuntu 中:

sudo apt-get install expect-dev

它是 expect-dev 的一部分,可以通过以下方式

unbuffer ls > log.txt

The unbuffer tool can assist with this issue:

It's part of the expect-dev and can be installed in ubuntu using

sudo apt-get install expect-dev

to use it type:

unbuffer ls > log.txt
秋心╮凉 2024-08-24 12:18:18

我猜你的程序中有类似的东西(你可以在测试中重现它,我在这里称之为 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< /code> 脚本 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

I guess you have something like this in your program (you can reproduce this for your tests, I'm calling it isatty here)

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

for example if you run it

$ ./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

Now if you create an expect script isatty.expect (install expect for your distro if not installed)

#! /usr/bin/expect -f

spawn "./isatty"
expect

and run it

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

or

$ ./isatty.expect > isatty.out 
$ cat isatty.out 
spawn ./isatty
0: is a TTY
1: is a TTY
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文