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 |
ローテーション後に実行するコマンド |
compress と delaycompress はセットで使うのが実務の鉄則。ローテーション直後のファイルをプロセスが書き続けている場合、即時圧縮すると書き込みが失敗する。
カスタム設定ファイルを書く
独自アプリのログを管理する場合は /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