🐧 Linux 総合学習プラットフォーム
自動化/定期実行 ・ 中級

ログローテーション(logrotate)

サーバーは動いている限りログを吐き続けます。放っておくとログファイルはどこまでも太り、いつかディスクを食い潰してサービスを止めてしまいます。これを防ぐのが logrotate です。古いログを区切って新しいファイルに交代させ、圧縮し、古すぎるものは捨てる。この世代交代を自動でこなします。設定は /etc/logrotate.d/ に1ファイル足すだけ。この回では書き方とテストの仕方、そして journald との住み分けを学びます。

サーバーのプロセスは、動いている間ずっとログを書き続ける。アクセスの記録、エラーの記録、処理の足あと。便利なのだが、ログファイルは黙って太っていき、放置すればいつかディスクをすべて食い潰す。

ディスクが満杯になると何が起きるか。新しいログが書けないどころか、データベースが書き込みに失敗し、サービスそのものが止まる。「原因はログの肥大でディスク満杯」というのは、運用のあるある事故の筆頭だ。

🔗
たとえログは家に届く郵便物のようなものだ。毎日少しずつ増え、捨てないと玄関が埋まる。logrotate は「古い分は箱にまとめて、さらに古い箱は処分する」係を自動でやってくれる。
💡
ポイントログは放っておくと必ずディスクを圧迫する。増やさない工夫ではなく、古いものを畳んで捨てる仕組みを最初から用意しておくのが正解だ。

🗂️ 世代交代という考え方

logrotate(ログローテート)は、ログファイルの世代交代を自動化するツールだ。ある大きさや期間に達したログを区切り、名前を付け替えて脇へどけ、まっさらな新しいファイルに書き込みを続けさせる。

どけられた古いログは、app.log.1、app.log.2 のように番号が振られて残る。新しいものが .1、その前が .2、と押し出されていき、決めた世代数を超えたいちばん古いものは捨てられる。これがローテーション(回転)と呼ばれるゆえんだ。

書き込み中app.logapp.log.1app.log.2app.log.3gz 圧縮捨てる新しい ←→ 古い

⚙️ 設定は数個のキーワードで決まる

logrotate の設定は、いくつかのキーワードを並べるだけで書ける。まず押さえたいのは4つだ。rotate は残す世代数、daily は毎日区切る指定、compress は古い分を gzip で圧縮する指定、missingok はログが無くてもエラーにしない指定になる。

/var/log/app/app.log を、毎日・7世代・圧縮つきで管理する設定はこう書ける。 { daily rotate 7 compress missingok notifempty }

この設定なら、毎日1回ログを区切り、直近7日分を残し、古いものは圧縮して置き、8日目に押し出された分は消える。notifempty は「中身が空なら区切らない」指定で、無駄な空ファイルが増えるのを防ぐ。

💡
ポイントdaily(頻度)・rotate(世代数)・compress(圧縮)の3つを決めれば骨格は完成する。まずはこの3語から始めれば十分に実用になる。
つまずきdaily の代わりに weekly や monthly も選べる。また size 100M のように「大きさで区切る」指定もある。頻度と世代数は、そのログがどれくらいの速さで増えるかを見て決める。

📁 /etc/logrotate.d/ に置くだけ

自分のアプリ用の設定は、本体の設定を直接いじらず、/etc/logrotate.d/ というディレクトリに1ファイル置くのが作法だ。ここに置かれたファイルは、まとめて自動で読み込まれる。

アプリ用の設定を1枚のファイルとして追い足す。ファイル名はアプリ名にしておくと分かりやすい。 $ sudo nano /etc/logrotate.d/myapp

この流儀のよい点は、パッケージを消せばこの1ファイルを消すだけで設定も消える、という後始末のしやすさにある。他のアプリの設定と混ざらないので、事故も起きにくい。

コツ多くのディストリでは logrotate 自体が毎日 cron や systemd timer 経由で自動起動している。だから設定ファイルを置けば、あとは決まった時刻に勝手に回る。手で毎回叩く必要はない。

📣 区切った後にサービスへ合図する

ここに一つ落とし穴がある。ログを脇へどけても、書き込んでいるサービスが古いファイルをつかんだままだと、新しいファイルに切り替わらず、消えたはずのファイルへ書き続けてしまうことがある。

これを防ぐのが postrotate だ。ローテーションの直後に実行したいコマンドを、postrotate と endscript の間に書く。ここでサービスに「ログを開き直せ」という合図(多くは reload やシグナル送信)を送る。

区切った直後に nginx にログを開き直させる。 { daily rotate 14 compress postrotate systemctl reload nginx endscript }
logrotateログを区切るpostrotatesystemctl reloadサービス新ファイルに書く「ログを開き直せ」の合図

🧪 流す前にテストする

設定を書いたら、いきなり本番で回す前に -d でテストする。-d は debug(デバッグ)モードで、実際にはファイルを動かさず「もし実行したらどう振る舞うか」を細かく表示してくれる。

特定の設定ファイルを指定して、動きを予行演習する。 $ logrotate -d /etc/logrotate.d/myapp

設定にミスがあればここで気づける。逆に、今すぐ強制的に1回転させて動作を確かめたいときは -f(force)を使う。ふだんの運用では自動任せで構わないが、初回の確認には便利だ。

💡
ポイント設定を変えたら -d で予行、確認できたら -f で1回試す。この2段構えなら、本番のログを壊さずに安全に育てられる。

📰 journald との住み分け

systemd を使う今どきのシステムには、journald というログの受け皿がもう一つある。journalctl で読むあのログだ。journald は自前の形式でログを溜め、こちらは logrotate ではなく設定ファイルの容量制限(SystemMaxUse など)で自動的に古いものを捨てる。

つまずきつまり、テキストのログファイル(/var/log 配下の .log)は logrotate、journald が抱えるログは journald 自身の容量設定、と担当が分かれる。両者は別々に効くので、ディスクを守るならどちらも見ておく必要がある。

自分でファイルにログを吐くアプリを運用するなら logrotate が主役になる。世代交代のしくみを一度用意しておけば、ディスク満杯という定番の事故から、サーバーを静かに守り続けてくれる。

この項目に出てくる用語

logrotateろぐろーてーと
肥大するログファイルを区切り・圧縮・世代管理して自動で捨てるツール。
ログの世代管理ろぐのせだいかんり
古いログを番号付きで残し、決めた世代数を超えた分から捨てていく管理方式。
postrotateぽすとろーてーと
ログを区切った直後に実行する処理。多くはサービスにログを開き直させる合図。

関連コマンド

logrotate

▶ 学習アプリでこの続きを学ぶ・演習する