我正在使用以下语句(简化版本):
tail -f -c+1 <filename>
为了将文件通过管道传输到进程。
不过,我发现末尾有许多行没有通过管道传输。
一个具体的例子是通过管道传输 mysql 文件,并在到达末尾时停止:
tail -f -c+1 mysqdump.sql | sed '/^-- Dump completed/ q0'
这不起作用 - 转储的最后一行-- Dump completed [...]
没有通过管道传输到 sed。
我的猜测是tail -f
,在这种情况下,缓冲区仅在已满时才会被刷新。
有谁知道我该如何解决这个问题?
=================
我找到了原因 - 描述不完整(并且代码没有表现出该行为)。
从压缩(lzma)文件进行管道传输时会发生此问题:
tail -f -c+1 <filename.lzma> | lzma -d | sed '/^-- Dump completed/ q0'
最有可能的是,tail
不发送最后一个压缩块,因为它没有检测到任何新行,因为输入是二进制的。
答案1
tail -f
在每个输入行后刷新。您可以使用strace
(或者truss
您的 UNIX 变体提供的任何用于跟踪进程的系统调用的内容)来确认这一点。
如果有不完整的行,tail -f
则继续等待下一个换行符。它是专为文本文件设计的工具。如果您需要尾部二进制文件(例如,如果-- Dump completed
后面没有换行符),则必须使用自定义工具。
如果您将sed
的输出重定向到远离终端的位置,它将进行自己的缓冲。尝试stdbuf
或者unbuffer
。
答案2
使用示例stdbuf -o0
。参考:https://superuser.com/a/1123674/126847
tail -F cpu.log | stdbuf -o0 tr '=' ' ' | stdbuf -o0 awk '$6 > 1'
答案3
问题中调用的命令的一个问题是sed
在缓冲模式下调用。
tail -f -c+1 <filename.lzma> | lzma -d | sed '/^-- Dump completed/ q0'
您需要添加-u
标志:
tail -f -c+1 <filename.lzma> | lzma -d | sed -u '/^-- Dump completed/ q0'
有关详细信息,请阅读有关-u
开关的信息 sed
手册页。