我在 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