ログローテーション(logrotate)
サーバーは動いている限りログを吐き続けます。放っておくとログファイルはどこまでも太り、いつかディスクを食い潰してサービスを止めてしまいます。これを防ぐのが logrotate です。古いログを区切って新しいファイルに交代させ、圧縮し、古すぎるものは捨てる。この世代交代を自動でこなします。設定は /etc/logrotate.d/ に1ファイル足すだけ。この回では書き方とテストの仕方、そして journald との住み分けを学びます。
サーバーのプロセスは、動いている間ずっとログを書き続ける。アクセスの記録、エラーの記録、処理の足あと。便利なのだが、ログファイルは黙って太っていき、放置すればいつかディスクをすべて食い潰す。
ディスクが満杯になると何が起きるか。新しいログが書けないどころか、データベースが書き込みに失敗し、サービスそのものが止まる。「原因はログの肥大でディスク満杯」というのは、運用のあるある事故の筆頭だ。
🗂️ 世代交代という考え方
logrotate(ログローテート)は、ログファイルの世代交代を自動化するツールだ。ある大きさや期間に達したログを区切り、名前を付け替えて脇へどけ、まっさらな新しいファイルに書き込みを続けさせる。
どけられた古いログは、app.log.1、app.log.2 のように番号が振られて残る。新しいものが .1、その前が .2、と押し出されていき、決めた世代数を超えたいちばん古いものは捨てられる。これがローテーション(回転)と呼ばれるゆえんだ。
⚙️ 設定は数個のキーワードで決まる
logrotate の設定は、いくつかのキーワードを並べるだけで書ける。まず押さえたいのは4つだ。rotate は残す世代数、daily は毎日区切る指定、compress は古い分を gzip で圧縮する指定、missingok はログが無くてもエラーにしない指定になる。
この設定なら、毎日1回ログを区切り、直近7日分を残し、古いものは圧縮して置き、8日目に押し出された分は消える。notifempty は「中身が空なら区切らない」指定で、無駄な空ファイルが増えるのを防ぐ。
📁 /etc/logrotate.d/ に置くだけ
自分のアプリ用の設定は、本体の設定を直接いじらず、/etc/logrotate.d/ というディレクトリに1ファイル置くのが作法だ。ここに置かれたファイルは、まとめて自動で読み込まれる。
この流儀のよい点は、パッケージを消せばこの1ファイルを消すだけで設定も消える、という後始末のしやすさにある。他のアプリの設定と混ざらないので、事故も起きにくい。
📣 区切った後にサービスへ合図する
ここに一つ落とし穴がある。ログを脇へどけても、書き込んでいるサービスが古いファイルをつかんだままだと、新しいファイルに切り替わらず、消えたはずのファイルへ書き続けてしまうことがある。
これを防ぐのが postrotate だ。ローテーションの直後に実行したいコマンドを、postrotate と endscript の間に書く。ここでサービスに「ログを開き直せ」という合図(多くは reload やシグナル送信)を送る。
🧪 流す前にテストする
設定を書いたら、いきなり本番で回す前に -d でテストする。-d は debug(デバッグ)モードで、実際にはファイルを動かさず「もし実行したらどう振る舞うか」を細かく表示してくれる。
設定にミスがあればここで気づける。逆に、今すぐ強制的に1回転させて動作を確かめたいときは -f(force)を使う。ふだんの運用では自動任せで構わないが、初回の確認には便利だ。
📰 journald との住み分け
systemd を使う今どきのシステムには、journald というログの受け皿がもう一つある。journalctl で読むあのログだ。journald は自前の形式でログを溜め、こちらは logrotate ではなく設定ファイルの容量制限(SystemMaxUse など)で自動的に古いものを捨てる。
自分でファイルにログを吐くアプリを運用するなら logrotate が主役になる。世代交代のしくみを一度用意しておけば、ディスク満杯という定番の事故から、サーバーを静かに守り続けてくれる。