サービスを停止せずにログローテーション(logrotate)を行う


さくらVPSにて行った設定。
サーバー設定に関しては素人の域を出ておらず、今回行った設定についても改善点は多いかとは思いますが、備忘録として残しておきます。
(もしかしたら解釈が間違っているものもあるかもしれません)

logrotate の設定

vim /etc/logrotate.conf
# see "man logrotate" for details
# rotate log files weekly
#weekly
daily

# keep 4 weeks worth of backlogs
#rotate 4
rotate 7

logrotate の実行を週1(weekly)から、毎日(daily)に変更。
ログを残すのは4世代分から7世代分に変更。

HTTPデーモンのログローテーション設定

vim /etc/logrotate.d/httpd
/var/log/httpd/*log {
    missingok
    notifempty
    sharedscripts
#    delaycompress
    postrotate
#        /sbin/service httpd reload > /dev/null 2>/dev/null || true
        /sbin/service httpd graceful > /dev/null 2>/dev/null || true
    endscript
}

「delaycompress」は、設定ファイル(/etc/logrotate.conf)で圧縮をかけない設定になっているためコメントアウト。
圧縮する設定になってないと無視されますが、不必要ならコメントアウトするか削除しておかないと、他の人がみたときに「圧縮処理をかけたいのに設定ファイルを書き換え忘れている」のか「無視されるから残している」のか判断がつき辛いですからね。
で、削除するとログの容量が増えてきて圧縮が必要になった時に戻すのが面倒なので、コメントアウトにしています。

「httpd reload」となっていたところを、「httpd graceful」に変更。
これにより、稼働中のプロセスは終了することなく、再起動の処理が行われる。
logrotate 実行時に稼働中だったプロセスは、そのまま旧ファイルにログが書き込まれる。

PHPのログローテーション設定

vim /etc/logrotate.d/php
/var/log/php/php_errors.log {
    missingok
    notifempty
    delaycompress
    copytruncate
}

先ほどの「httpd」のローテートとは違い、こちらでは「copytruncate」を使用してログファイルのローテーションをさせています。
「copytruncate」では、現在のログファイルをコピーして旧世代のファイルを作成しています。
その後現在のログファイルの中身を消去することで、再起動処理を必要とすることなくログのローテーションを可能としています。
ただしこの方法では、「ファイルコピー ~ 中身の消去」の間に発生したログは、どちらのファイルにも残らないという欠点があります。

PHPのログはそこまでの精度を求めていないのと、「httpd graceful」を行うよりサーバーへの負担が軽いのかな?と思って「copytruncate」にしていますが、もしかしたら両方「httpd graceful」でやった方が良いのかもしれません。
この辺の知識がまだまだ足りてないため、現在はこの設定にしています。
もう少し詳しくなったら、また設定を変えるかもしれません。

ディレクティブ説明

missingok 指定のログファイルが実在しなかったとしてもエラーを出さずに処理続行
notifempty 元のログファイルが空ならばローテーションしない
sharedscripts ローテーションの条件に合致するログが複数あった場合に、prerotate, postrotate のスクリプトを一度だけ実行する
delaycompress 圧縮処理を、その次のローテーションの時まで遅らせる。compress も指定しないと無意味
postrotate

endscript
実際にローテーションが行われた後 (lastaction よりは前) に実行するスクリプト。
copytruncate copy の動作を行った後、内容を消去する。これはログファイルをリロードする術のないプログラムへの対処法のひとつ。

参考サイト
Stray Penguin – Linux Memo (logrotate)

デバッグ

# 全テスト
logrotate -dv /etc/logrotate.conf

# 個別にテスト
logrotate -dv /etc/logrotate.d/httpd

「-d」でデバッグモード、「v」をつけると詳細表示。

実行ログの確認

less /var/lib/logrotate.status