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