tee -a 不重新创建文件

tee -a 不重新创建文件

我在 Raspberry Pi 3 Debian 最新版本上运行以下命令:

cat /dev/ttyUSB0 | tee -a /media/pi/KINGSTON/klima.out | grep -F $ | tee -a /media/pi/KINGSTON/log

该命令运行良好并执行其应有的操作;但是,当我删除(手动或通过 CRON)该klima.out文件时,它不会重新创建。命令继续运行,日志文件继续附加,但klima.out文件没有返回。 (也没有缓冲)。我想每周删除一次它,以免让它超出所有边界。有什么建议么?

答案1

我假设您的管道运行了很长时间,并且您试图在运行时删除日志文件。

当您删除文件时,tee进程仍将其打开以进行写入,这意味着磁盘空间不会交还给系统。在关闭所有引用该文件的打开文件描述符之前,这种情况不会发生。

只要在删除之前分配了文件描述符,就可以写入已删除的文件。

您必须重新启动管道才能重新创建文件,并允许回收旧(现在无名)日志文件占用的空间。

为了避免重新启动管道,您可以选择截短文件,即将其大小修剪为零而不删除它。这将允许tee继续追加到文件而无需重新打开它。

可以完成截断文件就像 jlliagre 在他的回答中所显示的那样,或使用truncate(属于 GNU coreutils 一部分的非标准实用程序):

truncate -s 0 /media/pi/KINGSTON/klima.out

的手册truncate有关该实用程序的更多信息。

答案2

如果要恢复文件块,则需要清空该文件,而不是取消链接:

这种便携式方式应该适用于大多数 shell:

: > /media/pi/KINGSTON/klima.out

取消链接文件(即rm)会删除目录条目,但只要文件保持由读取者或写入者打开状态,就不会影响文件内容(inode)。

答案3

您不了解系统如何处理文件。

您删除了文件条目,但只要程序保留其句柄,该文件仍然存在。所以 tee 永远不会收到条目被删除的通知,并且它仍然会写入文件!

由于硬链接(由 ln 命令创建),一个唯一的文件可以有许多条目。

您可以编写自己的 tee 版本,在写入文件的每一行上关闭和打开文件,但它的性能会非常低,因为它会生成如此多的系统调用。

这是一个 shell 函数,它将其输入拆分为多个文件:

splitSizeInKio=100

splitInput(){
    local PS4='+splitInput+ '
    set -x
    local i=0
    local fname="$1"
    local ii

    while true
    do if [ $i -lt 10 ]
       then ii=0$i
       else ii=$i
       fi
       local outfile="$fname".$ii
       dd of="$outfile" bs=1024 count=$splitSizeInKio
       i=$((i+1))
    done
}

(如果您溢出了多行而不是大小,则可以使用“head”而不是“dd”。)

使用 bash,您可以像这样使用“进程替换”:

prog1 | tee >( splitInput somefilename ) | prog2

相关内容