为什么以下命令不产生任何输出?
$ tail -f /etc/passwd | tail
Run Code Online (Sandbox Code Playgroud)
阅读有关缓冲后,我尝试了以下无济于事:
$ tail -f /etc/passwd | stdbuf -oL tail
Run Code Online (Sandbox Code Playgroud)
请注意,以下确实会产生输出:
$ tail /etc/passwd | tail
Run Code Online (Sandbox Code Playgroud)
这样做也是如此:
$ tail -f /etc/passwd | head
Run Code Online (Sandbox Code Playgroud)
我使用的是尾部版本 8.21(GNU coreutils)。
Gha*_*ima 37
tail -f
尾巴其实是现在不tail
知道的东西,下一个怎么知道。另一方面tail -f
,头部是已知的,因此可以进行处理。
或者更简单地说:tail
相对于文件的末尾,但输出流tail -f
没有 EOF(至少在其终止之前没有)。
如果您找到第一个tail
的 pid 并杀死它,那么您应该会看到第二个的输出。
sle*_*anc 21
当以流作为输入运行时,tail
保留一个n
-line 缓冲区,它在读取流时填充该缓冲区,但在到达流末尾之前无法输出这些行,即EOF
在尝试从输入读取时收到特殊代码溪流。调用tail -f
不会退出,因此它永远不会关闭它的流,这使得不可能返回该流的最后 10 行。
bis*_*hop 17
tail
显示最后 X 行。 tail -f
做同样的事情,但本质上是一个无限循环:在启动时,显示文件的最后 X 行,然后使用一些操作系统魔法(如 inotify),监视并显示新行。
要完成它的工作,tail
必须能够定位到文件的末尾。 如果tail
找不到文件的结尾,则无法显示最后 X 行,因为“last”未定义。那么tail
在这种情况下做什么呢?它一直等到它确实找到文件的结尾。
考虑一下:
$ chatter() { while :; do date; sleep 1; done; }
$ chatter | tail -f
Run Code Online (Sandbox Code Playgroud)
这似乎永远不会取得进展,因为从chatter
.
如果您要求tail
从文件系统管道中提供最后几行,您会得到相同的行为。考虑:
$ mkfifo test.pipe
$ tail test.pipe
Run Code Online (Sandbox Code Playgroud)
stdbuf
绕过感知的问题是一种崇高的尝试。但关键的事实是,I/O 缓冲并不是根本原因:缺乏明确的文件结尾才是。如果您查看tail.c 源代码,您会看到file_lines
函数注释如下:
END_POS 是 EOF 的文件偏移量(比最后一个字节的偏移量大一个)。
这就是魔法。您需要一个文件结束符让 tail 在任何配置中工作。 head
没有那个限制,它只需要一个文件开头(它可能没有,试试head test.pipe
)。面向流的工具,如sed
和awk
既不需要文件的开头或结尾:他们对缓冲区的工作。