Linuxサーバでのログローテーション(logrotate)最小設定集
(たまに数GBになってるログ、ありますよね対策)
運用していると、気づいたら /var/log/ 配下やアプリのログが数GBになっていて、
- ディスクが逼迫する
- grep/less が重い
- ログ出力が止まる(アプリが書けずにエラー)
みたいな事故につながりがちです。
そこで「安全に」「最小の設定で」ログを回すための logrotate 設定の雛形をまとめます。
対象読者は「Linuxサーバを触る」「アプリのログファイルを置いている」くらいの方想定です。
(RHEL/CentOS系でもDebian系でも考え方は同じ。例はありがちな構成で書きます)
logrotate の基本(超要点)
- logrotate は 既存のログファイルをリネームして世代管理し、必要に応じて 圧縮します
- 通常は
cron(またはsystemd timer)から 1日1回くらいで回ります - 設定は以下のどちらか
- 全体設定:
/etc/logrotate.conf - 個別設定:
/etc/logrotate.d/*
- 全体設定:
多くのディストリでは、/etc/logrotate.conf の中で /etc/logrotate.d を include しています。
まず確認:そもそも動いてる?
cron(RHEL/CentOS系の典型)
-
/etc/cron.daily/logrotateがあるか確認
実行ログの確認(例)
-
/var/lib/logrotate/logrotate.status- いつどのログをローテートしたかの記録があります(目安)
最小の“安全寄り”テンプレ(アプリログ用)
例:アプリが /var/log/myapp/myapp.log に吐いていて、たまに数GBになるケース。
/etc/logrotate.d/myapp を作ります。
/var/log/myapp/myapp.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
dateext
}
各ディレクティブの意図(必要最小限だけ)
-
daily- 日次で回す(サイズが育ちやすいログに無難)
-
rotate 14- 14世代保持(2週間分)
-
compress- 古いログを gzip 圧縮して容量削減
-
delaycompress- 直近1世代分は圧縮しない
- ローテ直後にトラブル調査で開きたい時に便利(圧縮前提のツール問題も避ける)
-
missingok- ログがなくてもエラー扱いしない(初回や一時的に出ない場合に安全)
-
notifempty- 空なら回さない(無駄な世代が増えない)
-
copytruncate- アプリを再起動せずにローテするための定番
- “ファイルをコピー→元をtruncate(0)”する方式
-
dateext-
myapp.log-20260121.gzのように日付つきになる(世代が分かりやすい)
-
「安全に」やるための重要ポイント(ここだけは押さえる)
1) そのプロセスはログファイルを開きっぱなし?
多くのアプリはログファイルを open したまま書き続けます。
この場合、logrotate の「標準的な方式」(renameして新規作成)だけだと、
- アプリは**古いファイル(リネーム後)**に書き続ける
- 新しい
myapp.logが増えない - ローテしたつもりが容量が減らない
ということが起きます。
その対策が主に2つです。
- copytruncate を使う(アプリ側に何もしないで済むが後述の注意あり)
- アプリにログ再オープン(reopen)させる(より綺麗。できるならこっち)
「今回は忙しく、当たり障りなく確実に回す」なら、まずは copytruncate は選択肢として強いです。
2) copytruncate の注意点(理解して使う)
copytruncate は便利ですが副作用もあります。
-
コピー中に書き込みがあると、その一部が取りこぼされる可能性
- 厳密にログ欠落ゼロが必要な監査ログ等には不向き
- 大容量ログだと、コピーが重い(ディスクIOを食う)
- 数GB級で頻繁に回すなら、できればアプリ側で reopen できる方式へ
ただ、「数GBになって困る」系の一般的なアプリログなら、運用上許容されることが多いです。
(このへんが“安全寄りだけど現実的”な落とし所)
より良い方式:ログ再オープンできるなら postrotate を使う
アプリやデーモンが HUP シグナル等でログを開き直すなら、こちらが王道です。
(nginx や syslog 系などはこの手が使えることが多い)
例:/var/log/myapp/myapp.log を rename 方式で回し、アプリに reopen させる。
/var/log/myapp/myapp.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
dateext
create 0640 myapp myapp
postrotate
# 例:pidファイルがあるなら HUP を投げる
/bin/kill -HUP `cat /var/run/myapp.pid` 2>/dev/null || true
endscript
}
-
create 0640 myapp myapp- 新しいログファイルを 指定権限・所有者で作る(これがないと権限事故の元)
-
postrotate- ローテ後に reopen の合図を出す
こちらはログ欠落の可能性が減り、大容量でもコピーが走らないので軽いです。
ただし「アプリが reopen に対応している」ことが前提になります。
“数GBになりがち”向け:サイズ条件も併用する
日次でも間に合わない(1日で数GBなど)なら、サイズで回すのも現実的です。
/var/log/myapp/myapp.log {
size 200M
rotate 10
compress
delaycompress
missingok
notifempty
copytruncate
dateext
}
-
size 200M- 200MBを超えたらローテ(cron実行時に判定)
- 注意: logrotate自体は常駐ではないので、**「超えた瞬間」ではなく「次の実行時」**に回ります
- それでも「数GB化」はかなり抑えられます
テスト方法(本番投入前に必ず)
設定を書いたら、まずは デバッグ、次に 強制実行で挙動を見ます。
デバッグ(実際には回さない)
logrotate -d /etc/logrotate.d/myapp
強制実行(回す)
logrotate -f /etc/logrotate.d/myapp
回した結果、以下を確認します。
-
myapp.logが残っていて、書き込みが継続しているか - ローテファイルが生成され、圧縮もされているか
- 所有者/パーミッションが期待通りか(
ls -l)
よくある事故(このパターン多い)
-
ローテ後にアプリがログを書けなくなった
-
createを入れていない / owner が違う / パーミッションが厳しすぎる
-
-
回ったのに容量が減らない
- アプリが古いファイルに書き続けている(reopenが必要、またはcopytruncateにする)
-
圧縮でCPUが上がる
- サイズが大きい&回す頻度が高い。
delaycompressや保持世代、サイズ閾値を見直す
- サイズが大きい&回す頻度が高い。
まとめ(忙しい時の結論)
- 「とにかく数GBログを安全に回してディスク事故を避ける」なら、まずはこの形が無難:
/var/log/myapp/myapp.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
dateext
}
- 可能なら postrotate で reopen する方式に寄せる(copytruncateより綺麗)
- 投入前に
logrotate -dと-fで挙動確認する