logrotateについて全然知らなかったので勉強した時のメモ。
やりたいこととしては
- 特定のファイルだけ時間でローテートしたい
- ローテート対象のファイルはgzipで圧縮したい
- ローテート対象ファイルのファイル名はYYYYmmddHHMMとしたい
という感じ。
今回はnignxのログを時間ごとにローテートするようにしてみました。
使ったのが初めてだったので基本的な概要は以下で勉強しました
さっき気づいたこと
logrotateの3.8.5からhourly対応したらしい。
3.8.5未満の場合の話
以下がとても参考になりました。
apacheのlogrotateを1時間毎に吐き出そうとした記録
logrotateを1時間ごとに実行させる
1時間に1回logrotateが動くように/etc/cron.dailyの中のlogrotatedというファイルを/etc/cron.hourlyにコピーします。
$sudo cp /etc/cron.daily/logrotate /etc/cron.hourly/
これによってlogrotateコマンド自体が1時間に1回実行されますが、ローテートの周期としてweeklyなどの設定をしていれば何回実行されても1週間経過しないとローテートされないはずなので時間ごとにローテートしたくなくファイル群は特に影響は受けないかと思います。(1週間経過しているかの判定はデフォルトでは/var/lib/logrotate.statusの日時を参照します)
/etc/logrotate.d/nginxを編集する
/etc/logrotate.d/配下にあるアプリケーションごとの設定でsizeとnodateexを指定します。また、compressをコメントアウトします。(理由は後述)
$sudo vi /etc/logrotate.d/nginx /var/log/nginx/*log { create 0644 nginx nginx daily rotate 10 missingok notifempty #compress size 1 nodateext sharedscripts postrotate /etc/init.d/nginx reopen_logs endscript }
size指定することによって指定されたsizeを越えたらローテートします。(manでgrow bigger thanなので以上ではなく超えるだと思います、多分)なお、minsizeというオプションもありこちらを指定するとローテーション周期(daily,weeklyなど)とのAND条件となるので注意。logrotate の size と minsize の違い
また、nodateextを追記します。これによってローテートするときに日付をファイル名に付けるのではなく、hoge.1というようなファイル名が連番になるようにします。/etc/logrotate.confでdateextを指定していなければこちらで明示的に指定する必要はありません。
この状態で正常に動作するか確認します。
$sudo /usr/sbin/logrotate /etc/logrotate.conf Reopening nginx logs: [ OK ] $wget http://localhost/ $sudo /usr/sbin/logrotate /etc/logrotate.conf Reopening nginx logs: [ OK ] $sudo ls -la /var/log/nginx/ total 16 drwx------ 2 nginx nginx 4096 Jan 31 13:20 . drwxr-xr-x 6 root root 4096 Jan 25 03:13 .. -rw-r--r-- 1 nginx nginx 0 Jan 31 13:17 access.log -rw-r--r-- 1 nginx nginx 101 Jan 31 13:17 access.log.1 -rw-r--r-- 1 nginx nginx 101 Jan 31 13:16 access.log.2 -rw-r--r-- 1 nginx nginx 0 Jan 13 03:14 error.log
ファイル形式を変更して圧縮する
dateformatというオプションはあるのですが、Only %Y %m %dとなっているので時間が恐らく使えません。そのため、 ログローテーション後にスクリプトを実行できるpostrotate〜endscriptを使ってリネームを行います。また、その中で圧縮も行います。(compressオプションはpostrotate-endscriptの後にローテートした元々のファイルを圧縮しようとするようでリネームを独自でやると正しく動作しないようだった)
/var/log/nginx/*log { create 0644 nginx nginx daily rotate 10 missingok notifempty #compress size 1 nodateext sharedscripts postrotate EXT=`date +%Y%m%d%H%M` for f in $1 do ls $f.1 >/dev/null 2>&1 if [ $? -eq 0 ] ; then mv $f.1 $f.$EXT gzip $f.$EXT fi done /etc/init.d/nginx reopen_logs endscript }
postrotateの中では/bin/shが実行されるようでシェルスクリプトが記述できます。 詳細な仕様が書いてある所を発見できなかったのですが、動作確認したところ以下のようでした。
指定されているログファイル群の一つでもローテートの条件に合致する場合にスクリプトは実行される(access.logが0バイトを超えた場合でerror.logのファイルサイズが0バイトでもスクリプトが実行される)
第一引数に対象のファイル名が配列で渡される。ただし、ローテーション対象外のものも含まれる(access.logが0バイトを超えた場合でerror.logのファイルサイズが0バイトでもaccess.logとerror.logを含む配列が渡される)
あんまり綺麗に書けている自信がありませんが、動作的には大丈夫そうです。
以下のような方法では如何でしょうか?
返信削除---
/var/log/nginx/*log {
create 0644 nginx nginx
rotate 10
dateext
dateformat -%Y%m%d%d%d%d
compress
sharedscripts
lastaction
EXT1=`/bin/date +%Y%m%d%d%d%d`
EXT2=`/bin/date +%Y%m%d%H%M%S`
for f in ${1}; do
if [ -f ${f}-${EXT1}.gz ]; then
/bin/mv -f ${f}-${EXT1}.gz ${f}-${EXT2}.gz
fi
done
/etc/init.d/nginx reopen_logs
endscript
}
---
1.postrotate だと圧縮処理の前ですが、lastaction だと圧縮処理の後になるので、自前圧縮処理を書かずに済む
2.dateext は指定できるルールが限定されているので、正規表現的に似たもので指定しておいて、lastaction側でリネーム
似たルールにしておくことで、logrotate 側の「旧ログファイル名マッチング」が上手く動作するようになるので、"rotate 10" 等の世代管理指定が正しく作用する