ログが肥大化→ディスク圧迫→障害 を防ぐには、logrotate で 定期ローテーション+圧縮+世代管理 を回すのが実務の定番です。ここでは コピペで導入できる最短レシピ と、Nginx/Apache/アプリの設定例、検証方法、事故防止ポイントまで一気にまとめます。
まずは最短レシピ(コピペ可)
目的:日次で圧縮、14世代保持、空ファイルはスキップ、日付サフィックス、権限を揃えて作成。
/etc/logrotate.d/myapp を新規作成:
/var/log/myapp/*.log {
daily # 日次
rotate 14 # 14世代保持
missingok # 無くてもエラーにしない
notifempty # 空なら回さない
compress # .gz圧縮
delaycompress # 直近は生のまま、次回に圧縮
dateext # ファイル名に日付付与
dateformat .%Y-%m-%d # 例: app.log.2025-08-23
create 0640 app app # 新規ログの権限/所有者
su app app # 権限不足で失敗しないよう昇格
# アプリがログファイルを開き直せない場合は copytruncate を使う(下記参照)
}
動作確認
# ドライラン(実行せず計画だけ表示)
sudo logrotate -d /etc/logrotate.d/myapp
# 強制実行(挙動を確認)
sudo logrotate -f /etc/logrotate.d/myapp
logrotate の実行履歴は通常 /var/lib/logrotate/status に記録されます。
「copytruncate」か「シグナル再オープン」か(選び方)
- copytruncate:現在のファイルをコピーしてから元ファイルをその場で空に。
→ 便利だがごく稀にログ欠損の瞬間があり得る。 - シグナル再オープン:
postrotateでプロセスにUSR1やreloadを送り、新しいファイルで再開。
→ 正確で安全。推奨(対応するアプリが多い)。
copytruncate 版(簡単)
/var/log/myapp/*.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
dateext
dateformat .%Y-%m-%d
create 0640 app app
su app app
copytruncate # ← これを使う
}
シグナル再オープン版(推奨)
/var/log/myapp/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
dateext
dateformat .%Y-%m-%d
create 0640 app app
su app app
sharedscripts
postrotate
# 例: systemdサービスに USR1 を送ってログを開き直す
/bin/systemctl kill -s USR1 myapp.service >/dev/null 2>&1 || true
endscript
}
日次/週次/容量トリガの切り替え
# 週次ローテーション
weekly
rotate 8
# 容量トリガ(100MB以上なら回す)
size 100M
# 日次+容量(“毎日または100MB以上”で回す)
daily
size 100M
# 最長保持日数で頭打ち(例: 60日超は削除)
maxage 60
# このサイズ未満なら回さない(minsize)
minsize 1M
圧縮・保管の最適化
compress # gzip
# 並列圧縮(pigz)があれば速い
# compresscmd /usr/bin/pigz
# uncompresscmd /usr/bin/unpigz
# 回転後ファイルの保管先(同一FS上に限る)
olddir /var/log/myapp/old
olddirは同一ファイルシステム内でのみ有効。別ディスクに逃がすなら、ローテ後にpostrotateでrsyncなどを叩くのが現実的。
実例:Nginx のアクセスログ
/var/log/nginx/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
dateext
dateformat .%Y-%m-%d
create 0640 www-data adm # Debian/Ubuntu 系の例
su root adm
sharedscripts
postrotate
# Nginx にログ再オープンを通知(安全)
/bin/systemctl kill -s USR1 nginx.service >/dev/null 2>&1 || true
endscript
}
実例:Apache (httpd / apache2)
/var/log/httpd/*log /var/log/apache2/*log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
dateext
dateformat .%Y-%m-%d
create 0640 root adm
su root adm
sharedscripts
postrotate
# ディストリに合わせてどちらか
/bin/systemctl reload httpd.service >/dev/null 2>&1 || true
/bin/systemctl reload apache2.service >/dev/null 2>&1 || true
endscript
}
実例:アプリ独自ログ(再オープン非対応)
/var/log/myapp/app.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
dateext
dateformat .%Y-%m-%d
create 0640 app app
su app app
copytruncate # ← 再オープン不可ならこちら
}
実行スケジュールの確認(cron / systemd timer)
多くのディストリでは logrotate は自動で1日1回動いています。
# cronの場合
cat /etc/cron.daily/logrotate
# systemd timer の場合
systemctl status logrotate.timer
systemctl list-timers | grep logrotate
バックアップ連携(ローテ後に転送)
ローテ完了時に、S3やバックアップサーバへ送る例:
/var/log/myapp/*.log {
daily
rotate 30
missingok
notifempty
compress
delaycompress
dateext
dateformat .%Y-%m-%d
create 0640 app app
su app app
sharedscripts
postrotate
# 前回の圧縮済みファイルを転送(例: rsync)
/usr/bin/find /var/log/myapp -name "*.gz" -mtime -1 -print0 \
| xargs -0 -r -I{} rsync -a {} backup@host:/srv/logs/myapp/
endscript
}
トラブル防止チェックリスト
- ✅ ドライラン:
logrotate -dでまず挙動確認 - ✅ 権限:
su/createを適切に設定 - ✅ copytruncate vs 再オープン:可能なら再オープン方式を選ぶ
- ✅ 日付付与:
dateext+dateformatで世代識別を容易に - ✅ 保持数と期限:
rotateとmaxageの両方で制御 - ✅ 失敗検知:
/var/lib/logrotate/statusと/var/log/syslog(またはjournalctl)を定期確認 - ✅ 復旧手順:誤設定で巨大化しても
-fで手動回転して緊急退避
補足:journald(systemd)のログは別物
/var/log/journal を使う systemd-journald は logrotate ではなく /etc/systemd/journald.conf で管理します:
# /etc/systemd/journald.conf (抜粋)
SystemMaxUse=2G # 全体の上限
SystemMaxFileSize=200M # 1ファイル上限
MaxRetentionSec=30day # 保持期間
反映:
sudo systemctl restart systemd-journald
まとめ
- logrotate で 自動ローテーション+圧縮+世代保持 を標準化すれば、ディスク障害の芽を摘めます。
- 迷ったらまずは 日次+14世代+gzip+日付付与、再オープンできるサービスは
postrotateで通知。 - 運用開始前は ドライラン→強制実行で確認、導入後は状態ファイルとログを定期チェック。
このページのテンプレを貼り付け → ドライラン → 本番、の流れで 今日から“詰まないログ運用” を始めましょう。

コメント