logrotate 入門 - ログを溜めずに回す

logrotate 入門 - ログを溜めずに回す

logrotate とは何か?

logrotate はログファイルを定期的にローテーション(切り替え・圧縮・削除)するツール。放置すると /var/log 配下が無限に膨れてディスクを食い尽くすため、Ubuntu / RHEL 系ともにデフォルトでインストールされており、cron から毎日自動実行される。

ひとことまとめ

  • ログを自動で切り替え・圧縮・削除する常駐タスク
  • 設定は /etc/logrotate.conf(グローバル)と /etc/logrotate.d/(アプリ別)の 2 層構造
  • デバッグは logrotate -d から始める

ログを回さないとどうなるか?

ログを回さない場合、nginx・MySQL・syslog のログが数 GB に達してディスクが満杯になり、サービスが No space left on device で停止する。定期的に cron から /etc/cron.daily/logrotate が呼ばれており、設定さえ書けば自動で管理される。

cat /etc/cron.daily/logrotate
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.conf

設定ファイルの構造はどうなっているか?

logrotate は 2 層の設定を持つ。/etc/logrotate.conf がグローバルデフォルトを定義し、末尾の include 行で /etc/logrotate.d/ 配下を一括取込む。

/etc/logrotate.conf        ← グローバル設定
/etc/logrotate.d/          ← アプリ別設定(主戦場)
├── nginx
├── mysql-server
├── rsyslog
└── ...

典型的な /etc/logrotate.conf:

cat /etc/logrotate.conf
weekly
rotate 4
create
dateext
compress
include /etc/logrotate.d

weekly / rotate 4 はグローバルデフォルト。アプリ別設定で上書きできる。

/etc/logrotate.d/nginx の例(パッケージが自動生成したもの):

cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        postrotate
                if [ -f /run/nginx.pid ]; then
                        kill -USR1 `cat /run/nginx.pid`
                fi
        endscript
}

主要ディレクティブを押さえる

実務で使うディレクティブをまとめる。

ディレクティブ 意味
daily / weekly / monthly ローテーション頻度
rotate N 保持する世代数(例: rotate 7 = 7 世代分保持)
size N 指定サイズ超過時にローテーション(例: size 100M
compress gz 圧縮する
delaycompress 直前世代の圧縮を 1 サイクル遅らせる
missingok ログファイルが無くてもエラーにしない
notifempty 空ファイルはローテーションしない
create MODE USER GROUP ローテーション後に空ファイルを生成
dateext 世代ファイルに日付サフィックスを付ける
sharedscripts ワイルドカード対象全ファイルで postrotate を 1 回だけ実行
postrotate / endscript ローテーション後に実行するコマンド

compressdelaycompress はセットで使うのが実務の鉄則。ローテーション直後のファイルをプロセスが書き続けている場合、即時圧縮すると書き込みが失敗する。

カスタム設定ファイルを書く

独自アプリのログを管理する場合は /etc/logrotate.d/myapp を新規作成する。

/var/log/myapp/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    dateext
    sharedscripts
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}

ポイント:

  • sharedscripts を付けないと *.log にマッチしたファイルの数だけ postrotate が実行される
  • postrotate の最後に || true を付けると、サービスが停止中でも logrotate がエラー終了しない
  • nginx は kill -USR1、Apache は apachectl graceful、systemd サービスは systemctl reload でログファイルを再オープンする

動作確認はどうするか?

設定を書いたらまず logrotate -d(ドライラン)で確認する。ファイルを一切変更しない。

logrotate -d /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/myapp/*.log  after 1 days (30 rotations)
...
rotating log /var/log/myapp/access.log, log->rotateCount is 30
...
not rotating log, since it was already rotated less than 1 days ago

「already rotated less than 1 days ago」と出た場合は -f で強制実行できる。

logrotate -f /etc/logrotate.d/myapp

-f/var/lib/logrotate/status のタイムスタンプを無視して強制実行する。同一設定を短時間に複数回 -f すると世代ファイルが上書きされるため、テスト後は状態ファイルを確認する。

ローテーション状態を確認:

cat /var/lib/logrotate/status
logrotate state -- version 2
"/var/log/myapp/access.log" 2026-6-1-3:0:0
"/var/log/nginx/access.log" 2026-6-1-3:0:0

よくあるミスと対処

postrotate が効かない

ローテーション後もサービスが旧ファイルに書き続ける場合、postrotate のシグナル送信を忘れているか、sharedscripts の有無が問題の場合が多い。lsof で旧ファイルを掴んだままのプロセスを確認できる。

lsof | grep deleted | grep log

dateext 重複エラー

同一日に logrotate -f を 2 回実行すると dateext のサフィックスが重複してエラーになる。テスト環境では dateformat -%Y%m%d-%s(秒単位)を追加するか、世代ファイルを手動で削除してから再実行する。

ディレクトリ・ユーザーが存在しない

create 0640 www-data adm のユーザー・グループがシステムに存在しないとローテーションに失敗する。logrotate -v で詳細エラーを確認し、id www-data でユーザーの存在を確認する。

logrotate -v /etc/logrotate.d/myapp 2>&1 | head -30

次に読む