在 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
那就不一样了。