使用tee命令连续输出C程序的内容

3

这一定很简单,但是我没能理解。

这是一个将内容输出到标准输出的简单C程序:

root@oceanLondon:~/tst# cat tst.c
#include <stdio.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
        for (; ;) {
                printf("Hello world!\n");
                sleep(1);
        }
        return 0;
}

现在,如果我想将输出写入屏幕和文件:
root@oceanLondon:~/tst# ./tst |tee file

我的程序无法正常运行,屏幕和文件都是空的。

如果我写一个退出程序,那么它就可以完美地运行,例如:

root@oceanLondon:~/tst# ls |tee file
Makefile
file
qq
tst
tst.c
tst.o
root@oceanLondon:~/tst# cat file
Makefile
file
qq
tst
tst.c
tst.o
root@oceanLondon:~/tst#

这是一种缓冲问题吗?有人能帮我在持续运行的程序上执行tee命令吗?


6
如果你尝试fflush(stdout);会发生什么? - fredtantini
1
@fredtantini:那确实可以了。真的很简单。谢谢-随意将其发布为答案。 - wick
1
这里似乎有一些有用的答案(https://dev59.com/Kmgu5IYBdhLWcg3wbGel)。 (我现在不在Linux机器上,所以无法尝试它们。) - M Oehm
1
由于这个问题的唯一答案已被删除,@fredtantini,也许你应该发表一个回答。 - Tom Fenech
1
标准输出通常在直接输出到终端时是行缓冲的。当它输出到管道时,通常是完全缓冲的。您可以在每次迭代中使用 fflush(),或调用 setvbuf() 显式地将标准输出设置为行缓冲。 - Jonathan Leffler
显示剩余3条评论
2个回答

2

如果可以确定流引用的是一个交互设备(例如终端),则标准输出流是行缓冲的,否则它是完全缓冲的。因此,在某些情况下,即使有换行符要打印,像管道或重定向输出,printf也不会刷新。

> tst | tee file
> tst > file

在使用 printf() 后调用 fflush(stdout) 可以解决问题。
相关文本来自 C99 的第 7.19.3 节,其中指出:

当流为无缓冲流时,字符将尽快从源或目的地显示。否则,字符可能会被积累并作为块传输到或从主机环境中传输。

当流完全缓冲时,当缓冲区填满时,字符将被传输到或从主机环境中作为块传输。

当流为行缓冲时,当遇到新行字符时,字符将被传输到或从主机环境中作为块传输。

最初打开时,标准错误流不是完全缓冲的;仅当可以确定流不引用交互式设备时,标准输入和标准输出流才是完全缓冲的。


你的回答似乎与你的引用相矛盾。(回答中提到了“行缓冲”,而引用中则提到了“全缓冲”) - user12205
1
@ace,你说得完全正确,我已经修复了。非常感谢! - Alper

0

看起来你的问题是stdout被缓存了,在换行符后没有显示。你可以在printf语句后强制刷新它以显示:

fflush(stdout); 

或者,您可以通过以下方式禁用缓冲:

setbuf(stdout, NULL);

此外,请注意stderr不是缓冲的,您可以通过将内容打印到stderr而不是stdout来检查问题是否为缓冲问题。

正如您所注意到的那样,您还可以使用stdbuf(有关更多信息,请参见this answer)。


如果你编辑你的回答并包含这个链接:https://dev59.com/Kmgu5IYBdhLWcg3wbGel#11337109,我会接受它。 - wick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接