使用 `tail -f` 时文件被截断时清屏

问题描述 投票:0回答:4

我正在使用

tail -f
打印不断变化的文件的内容。当文件被截断时,它会显示如下:

blah (old)..
blah more (old)..
tail: file.out: file truncated
blah..
blah more..

当我过于频繁地更改文件时,这可能会变得混乱,以至于很难看到文件的开始/结束位置。有没有办法在文件被截断时以某种方式

clear
屏幕,以便它会像这样显示?

tail: file.out: file truncated
blah..
blah more..
bash tail gnu-coreutils
4个回答
15
投票

我知道这已经很旧了,但另一个(可能更简单)的解决方案是:

watch -n 1 cat myfile.txt


10
投票

您可以使用

perl
单行过滤
tail -f

的输出

例如

tail -f myfile.txt 2>&1 | perl -ne 'if (/file truncated/) {system 'clear'; print} else {print}'

1
投票

tailf myfile.txt

这是命令 tailf 而不是 tail -f

使用此命令,屏幕上不会返回任何被截断的文件


0
投票

万一其他人在 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
    不同,文件内容不会被解释,并且终端颜色保持不变
  • 与 Benj 的 perl one-liner 不同,文件内容本身并不能导致清晰

缺点:

  • 当立即覆盖大于 2048 字节阈值的文件时,截断可能会被忽视。因此,该脚本在监视正在编辑的文本文件时效果不佳。
  • 每次写入文件都会导致
    stat
    tail
    head
    各执行一次

注意: 使用inotifywait时,移动或删除文件将导致脚本退出。有些文本编辑器会这样做(例如

vim
)。

© www.soinside.com 2019 - 2024. All rights reserved.