默认的 stdout 缓冲是如何设置的?

默认的 stdout 缓冲是如何设置的?

在 Red Hat EL7 上运行,我们的日志文件中有这些很长的行,所以我做了一个

tail -f Log | cut -c1-$COLUMNS

这在某些系统上效果很好,但在其他(显然相同)系统上,管道保存数据直到缓冲区已满。当我打字时,SE 给了我使用时回答:

tail -f Log | stdbuf -oL cut -c1-$COLUMNS

做我需要的,但我想知道有什么不同。我希望系统运行得一样,无论好坏。

是否已设置默认缓冲?它是如何设置的以及在哪里设置的?

更新:我在出现问题的系统中打开了两个窗口并尝试:

while date; do usleep 500000 ; done | cut -c1-100

并且没有输出(直到缓冲区已满)。在另一个窗口中,我对剪切过程运行 strace 并得到了一系列无尽的信息:

read(0, "Wed Oct 26 13:04:12 CDT 2022\n", 4096) = 29
read(0, "Wed Oct 26 13:04:12 CDT 2022\n", 4096) = 29
read(0, "Wed Oct 26 13:04:13 CDT 2022\n", 4096) = 29
read(0, "Wed Oct 26 13:04:13 CDT 2022\n", 4096) = 29
read(0, "Wed Oct 26 13:04:14 CDT 2022\n", 4096) = 29
read(0, "Wed Oct 26 13:04:14 CDT 2022\n", 4096) = 29
read(0, "Wed Oct 26 13:04:15 CDT 2022\n", 4096) = 29

我认为这是非常确凿的证据,表明削减正在起到缓冲作用。但它是如何决定这样做的呢?

答案1

通常的行为是终端的输出是行缓冲的,而其他任何内容都是块缓冲的。参见例如GNU glibc 手册

新打开的流通常是完全缓冲的,但有一个例外:连接到交互式设备(例如终端)的流最初是行缓冲的。 [...]

所以像

grep ... | cut ...

将有grep缓冲其输出,但不缓冲cut.您可以通过运行stdbuf -o0 grep ...(或grep --line-buffered) 来解决这个问题。或者使用许多其他解决方法之一,请参阅:关闭管道中的缓冲

另一方面,tail -f不应该缓冲其输出。

stdbuf -oL当然,这与你所说的使用on不符cut修复它;它应该已经对其输出进行行缓冲。如果它要去终端,那就是。如果你有| cut ... > somefile那就不一样了。

相关内容