ログファイルの最後のn行だけを維持する方法は?

ログファイルの最後のn行だけを維持する方法は?

私は何かをした後、独自のログファイルにいくつかの行を追加するスクリプトを書いています。最後のものだけを残したい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.logtail

インストールする

spongeDebianシリーズシステムにインストールするには:

apt-get install moreutils

RHEL/CentOS システムにインストールするには、spongeEPEL リポジトリを追加し、次の手順を実行します。

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開きます。filen切り捨てなしとの違いは、<>;リダイレクトされたコマンドが成功すると、ksh93コマンドが離れた時点でfdに対して暗黙の操作が実行されることです。ftruncate()

他のシェルの場合でも同じことができます。

{
  tail -n 5 file.log &&
    perl -e 'truncate STDOUT, tell STDOUT'
} 1<> file.log

関連情報