📝
logrotateしたファイルをcatしてtail -fする
logrotate すると some-log.1 のようなファイルに順次内容が逃がされていく。cat some-log.* すればそれらを結合して眺められるが、最新のデータも結合してかつ tail -f のようにリアルタイムに更新分が追加されて欲しい場合はどうするかというメモ。
以下のようにする。
LOG_FILE=/var/log/some-log
{ ls -r ${LOG_FILE}.* | xargs cat; tail -F ${LOG_FILE} 2> /dev/null; }
ls -r はlogrotateした過去のファイルから結合するために逆順に得られるようにしている。
cat した過去のログファイルと、最新のログファイルを tail -F したものを {} で結合して表示する。tail -f ではなく -F なのはlogrotateされた場合に同じ名前の新しいファイルを開き直すため。その際のエラーメッセージを除外するため標準エラー出力をリダイレクトする。
さらにパイプで別の処理につなげたい場合には ==> var/log/some-log <== のようなヘッダが邪魔になるので、その場合は tail -q で表示しないようにする。{ command1; command2} の出力はそのままパイプで渡せるらしい。例えばjqで時刻フィールドだけ表示させると以下のようになる。
LOG_FILE=/var/log/some-log
{ ls -r ${LOG_FILE}.* | xargs cat; tail -Fq ${LOG_FILE} 2> /dev/null; } | jq '.timestamp'
Discussion
GNU tail の場合は
tail -Fで出来まする... ( https://www.gnu.org/software/coreutils/manual/html_node/tail-invocation.html )ホントダァァ😇(macOS にもありました
良い休日の回り道でした。
ちょっと勘違いしていたのですが、
tail -Fはinodeではなく名前を追跡するオプションなんですね。今回私が欲しかったのは過去のログ(本文の例の場合はsome-log.{1,2,...})もまとめてtail -fできるような方法でした。ただ、logrotate がかかると対象のログファイルがinodeが違う新しいファイルに置き換わるというのは盲点でした。
それで色々手元で試したところ
{ ls -r log.* | xargs cat; tail -Fq log; }が私の欲しかったものに近い挙動をするようです。