通常,stdout
是行缓冲的。换句话说,只要printf
参数以换行符结束,就可以立即打印该行。当使用管道重定向到tee
时,这似乎不成立。
我有一个C程序a
,它将始终以n
结尾的字符串输出到stdout
。
当它自己运行时(./a
),一切都会像预期的那样在正确的时间正确打印。但是,如果通过管道将其传递给tee
(./a | tee output.txt
),则在退出之前它不会打印任何内容,这就违背了使用tee
的目的。
我知道我可以通过在C程序中的每个打印操作之后添加一个fflush(stdout)
来修复它。但有没有更干净、更容易的方法呢?例如,有没有我可以运行的命令来强制stdout
进行行缓冲,即使在使用管道时也是如此?
7条答案
按热度按时间2q5ifsrm1#
你可以试试
stdbuf
手册页的(大)部分:
不过,请记住这一点:
您没有在
tee
上运行stdbuf
,而是在a
上运行它,所以这应该不会影响您,除非您在a
的源代码中设置了a
的流的缓冲。此外,
stdbuf
不是POSIX,而是GNU-coreutils的一部分。kcwpcxri2#
尝试
unbuffer
(man
page),它是expect
包的一部分。您的系统中可能已经有它了。在您的例子中,您可以这样使用它:
unbuffer ./a | tee output.txt
-p
选项用于管道模式,在这种模式下,unBuffer从stdin读取数据并将其传递给其余参数中的命令。tvz2xvvm3#
您可以使用stdio.h中的setlinebuf。
这应该会将缓冲更改为“行缓冲”。
如果需要更大的灵活性,可以使用setvbuf。
blmhpbnm4#
您还可以尝试使用
script
命令在伪终端中执行您的命令(该命令将强制行缓冲输出到管道)!请注意,
script
命令不会传回WRAPPED命令的退出状态。hmae6n7t5#
@处的
expect
包中的unbuffer
命令暂停,直到进一步通知答案不适用于我所呈现的方式。而不是使用:
./a | unbuffer -p tee output.txt
我不得不使用:
unbuffer -p ./a | tee output.txt
(
-p
用于管道模式,在该模式下,unBuffer从stdin读取并将其传递给其余参数中的命令)expect
程序包可以安装在:1.带
pacman -S expect
的MSYS21.配备
brew install expect
的Mac OS更新
我最近在一个外壳脚本中遇到了
python
的缓冲问题(在尝试将时间戳附加到其输出时)。修复方法是通过以下方式将-u
标志传递给python
:1.
run.sh
与python -u script.py
1.
unbuffer -p /bin/bash run.sh 2>&1 | tee /dev/tty | ts '[%Y-%m-%d %H:%M:%S]' >> somefile.txt
1.此命令将在输出上加上时间戳,并同时将其发送到文件和标准输出。
1.
moreutils
包可以安装ts
程序(时间戳)。更新2
最近,也遇到了
grep
缓冲输出的问题,当我在grep
上使用参数grep --line-buffered
时,它停止缓冲输出。z4iuyo4d6#
如果改用C++流类,则每个
std::endl
都是隐式刷新。使用C样式打印,我认为您建议的方法(fflush()
)是唯一的方法。fykwrbwg7#
最好的答案是
grep
的--line-buffer
选项,如下所述:https://unix.stackexchange.com/a/53445/40003