我有通过 cron 作业下载的日志文件。如果在远程位置更新文件,即使仅附加了数据,本地副本也会从头开始重写。
tail -f
像或这样的工具since
似乎将此视为“文件已被替换”并再次从头开始输出它们。即重复所有已知的内容。特别是这两个工具在 STDERR 上明确提到了这一点。
因此,如果我在一个终端中调用它:
for j in $(seq 2 4) ; do for i in $(seq 1 $j) ; do echo $i ; sleep 1; done > /tmp/foo; done
tail -f /tmp/foo
我在两个终端和tail -F /tmp/foo
另一个终端中都收到这些警告:
1
2
tail: /tmp/foo: file truncated
1
2
3
tail: /tmp/foo: file truncated
1
2
3
4
使用 时while sleep 0.25; do since /tmp/foo; done
,我收到以下错误消息之一:
1
2
since: considering /tmp/foo to be truncated, displaying from start
1
2
3
since: considering /tmp/foo to be truncated, displaying from start
1
2
3
4
since
显式使用 inode 而不是文件名作为文件的键。tail
可能会做类似的事情来识别被截断的文件。
我尝试过的另一个“工具”是 Perl 库文件::尾巴,但它有相同的“问题”,只是没有警告(至少在默认设置下)。
所以我想知道:是否有一种方法或工具不查看索引节点,而只查看文件的内容,并且仅在数据尚未附加时才重新启动?
我想要的只是这个输出:
1
2
3
4
(我见过tail -f,但是当文件被删除并重新创建时(不附加),但它没有帮助,因为它仍然从头开始重新输出文件的内容。)
是的,我知道这样的工具要么需要所有看到的(但未截断的)数据的缓存,要么至少需要它的哈希和。
答案1
这tail
对你的用例来说太聪明了。在这里,你可以这样做:
{
tail
while cat; do
sleep 1
done
} < /tmp/foo
与 的原始实现相同tail
(-f
1980 年添加到 SysIII 中)。
cat
最好使用内置和sleep
或有等效内置命令的shell 。或者在perl
/ python
...中执行
例如, in ksh93
,sleep
默认情况下是内置的,cat
可以使用 启用内置函数builtin cat
。在 中zsh
,您可以使用sysread
in 循环代替cat
和zselect
代替sleep
:
zmodload zsh/zselect
zmodload zsh/system
readall() while sysread -s 65536 -o1; do continue; done
{
tail
while readall; do
zselect -t 100
done
} < /tmp/foo
如果每次都创建一个新文件,tail -f
则不会检测到它。如果是这种情况,您仍然可以通过执行以下操作来做到这一点:
#! /bin/zsh -
zmodload zsh/zselect
zmodload zsh/system
readall() while sysread -s 65536 -o1; do continue; done
file=${1-/tmp/foo}
{
tail
(( offset = systell(0) ))
} < $file || exit
while true; do
if
sysopen -ru0 -- $file 2> /dev/null &&
sysseek $offset &&
readall
then
(( offset = systell(0) ))
fi
zselect -t 100
done
我们重新打开文件并在每次迭代时查找最后一个已知的偏移量。