我正在使用
tail -f
打印不断变化的文件的内容。当文件被截断时,它会显示如下:
blah (old)..
blah more (old)..
tail: file.out: file truncated
blah..
blah more..
当我过于频繁地更改文件时,这可能会变得混乱,以至于很难看到文件的开始/结束位置。有没有办法在文件被截断时以某种方式
clear
屏幕,以便它会像这样显示?
tail: file.out: file truncated
blah..
blah more..
我知道这已经很旧了,但另一个(可能更简单)的解决方案是:
watch -n 1 cat myfile.txt
您可以使用
perl
单行过滤 tail -f
的输出
例如
tail -f myfile.txt 2>&1 | perl -ne 'if (/file truncated/) {system 'clear'; print} else {print}'
tailf myfile.txt
这是命令 tailf 而不是 tail -f
使用此命令,屏幕上不会返回任何被截断的文件
万一其他人在 11 年后发现这里,我编写了一个稍微复杂的 bash 脚本来根据大小变化进行我想要的操作(监视日志文件):
#!/usr/bin/bash
set -e
FILE="$1"
#TODO verify $FILE is valid
LAST=0
while SIZE="$(stat -c '%s' "$FILE")"; do
# This will only trigger due to a race condition, since stat would normally fail
if [ "$event" = "DELETE_SELF" -o "$event" = "MOVE_SELF" ]; then
echo "Watch interrupted: file moved or deleted" 1>&2
exit 1
fi
# Small files might be overwritten without us ever seeing a smaller size
# To be safe, just print out everything again since it's not that much
if [ "$LAST" -le 2048 -o "$SIZE" -lt "$LAST" ]; then
clear
LAST=0
fi
if [ "$LAST" -lt "$SIZE" ]; then
# tail -c +N is 1-based!
tail -c "+$((LAST + 1))" "$FILE" | head -c "$(( SIZE - LAST ))"
LAST="$SIZE"
fi
read event
done < <(inotifywait -qme 'modify,close_write,delete_self,move_self' --format '%e' "$FILE")
它需要
inotifywait
包中的 inotify-tools
。或者,可以使用 sleep
定期检查受监控的文件。只需将最后两行替换为以下内容即可:
sleep 1
done
当使用 sleep 而不是 inotify 时,由于每次写入后不会立即检查文件大小,因此更有可能丢失截断。作为交换,除了 coreutils + clear 之外没有任何要求,并且对受监视文件的许多小写入不会导致资源使用量增加。
优点:
watch
不同,文件内容不会被解释,并且终端颜色保持不变缺点:
stat
、tail
和 head
各执行一次注意: 使用inotifywait时,移动或删除文件将导致脚本退出。有些文本编辑器会这样做(例如
vim
)。