私は何かをした後、独自のログファイルにいくつかの行を追加するスクリプトを書いています。最後のものだけを残したいNログファイルの行数(例:1000行)。これはスクリプトの最後で次のように実行できます。
tail -n 1000 myscript.log > myscript.log.tmp
mv -f myscript.log.tmp myscript.log
しかし、よりクリーンでエレガントなソリューションがありますか?たぶん単一のコマンドで実行できますか?
答え1
可能ですが、他の人が言ったように、最も安全なオプションは、新しいファイルを作成してから元のファイルを上書きしながらそのファイルを移動することです。
次の方法は行をBASHにロードするため、行数に応じてtail
ログ行の内容を格納するローカルシェルのメモリ使用量に影響します。
以下は、BASH評価の動作によりログファイルの末尾にある空白行も削除するため、"$(tail -1000 test.log)"
すべてのケースで実際に100%正確な切り捨てを提供するわけではありませんが、場合によっては十分です。
$ wc -l myscript.log
475494 myscript.log
$ echo "$(tail -1000 myscript.log)" > myscript.log
$ wc -l myscript.log
1000 myscript.log
答え2
このユーティリティは、sponge
このような状況のために設計されています。インストールした場合、2行は次のように書くことができます。
tail -n 1000 myscript.log | sponge myscript.log
通常、ファイルの書き込み中にファイルを読み取ることは信頼できません。この問題は、読み取りが完了してパイプが終了するまで書き込まないとsponge
解決されます。myscript.log
tail
インストールする
sponge
Debianシリーズシステムにインストールするには:
apt-get install moreutils
RHEL/CentOS システムにインストールするには、sponge
EPEL リポジトリを追加し、次の手順を実行します。
yum install moreutils
文書
からman sponge
:
sponge
標準入力を読み取り、指定されたファイルに書き込みます。シェルリダイレクトとは異なり、sponge
すべての入力は出力ファイルに書き込む前に吸収されます。これにより、同じファイルを読み書きするパイプラインを構築できます。
答え3
確かに「tail+mv」がいいですね!しかし、gnu sedの場合は試してみることができます。
sed -i -e :a -e '$q;N;101,$D;ba' log
答え4
ksh93シェルから:
$ seq -f 'This is line %g' 10000 > file.log
$ tail -n 5 file.log 1<>; file.log
$ cat file.log
This is line 9996
This is line 9997
This is line 9998
This is line 9999
This is line 10000
n<>; file
標準リダイレクト演算子と同様に、fdで読み取り+書き込みモードでn<> file
開きます。file
n
切り捨てなしとの違いは、<>;
リダイレクトされたコマンドが成功すると、ksh93
コマンドが離れた時点でfdに対して暗黙の操作が実行されることです。ftruncate()
他のシェルの場合でも同じことができます。
{
tail -n 5 file.log &&
perl -e 'truncate STDOUT, tell STDOUT'
} 1<> file.log