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
ファイルを開いたままにします。これは、ディスク領域がシステムに再提供されないことを意味します。これは、ファイルを参照するすべての開いているファイル記述子が閉じられるまで発生しません。
削除する前に、ファイル記述子が割り当てられている限り、削除されたファイルに書き込むことができます。
ファイルを再生成し、古い(現在の名前なし)ログファイルが占有していたスペースを回復するには、パイプラインを再起動する必要があります。
パイプラインを再起動したくない場合は、次を選択できます。カットつまり、ファイルを削除せずにサイズを0に切り捨てます。これにより、tee
ファイルを再度開かずにファイルに追加することができます。
ファイルをトリミングすることができます。jlliagreが彼の答えに示すように、または使用truncate
(GNU coreutilsの一部である非標準ユーティリティ):
truncate -s 0 /media/pi/KINGSTON/klima.out
バラより手動truncate
このユーティリティに関する追加情報。
答え2
ファイルブロックを回復するには、リンクを解除するのではなくファイルを空にする必要があります。
この移植可能な方法は、ほとんどのシェルで動作します。
: > /media/pi/KINGSTON/klima.out
ファイル(たとえばrm
)リンクを解除すると、ディレクトリエントリが削除されますが、ファイルがリーダーまたは作成者によって開かれている限り、ファイルの内容に影響はありません。
答え3
システムがファイルを処理する方法を理解していません。
ファイルエントリを削除してもプログラムがそのハンドルを保持している限り、ファイルは存在し続けます。したがって、ティーはアイテムが削除されたという通知を受け取らず、まだファイルに書き込みます。
ハードリンク(lnコマンドで生成された)のため、一意のファイルに多くのエントリがある可能性があります。
ファイルに書き込まれたすべての行でファイルを閉じて開く独自のティーバージョンを作成できますが、あまりにも多くのシステムコールを生成するため、非常に非効率的です。
以下は、入力を複数のファイルに分割するシェル関数です。
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
}
(サイズの代わりに複数行があふれている場合は、「dd」の代わりに「head」を使用できます。)
Bashでは、次のように「プロセス置換」を使用できます。
prog1 | tee >( splitInput somefilename ) | prog2