mv)、圧縮(gzip)し、保存期間を過ぎたものを削除する、ローテートと呼ばれる操作を行う必要がある。RHELやCentOSでは、logrotateというコマンドでこれを行う。この
logrotateの設定ファイルは、/etc/logrotate.confおよび、その中から読み出される/etc/logrotate.d/*である。詳しくは、logrotate(8)を参照のこと。さて、この
logrotateを使って、複数のサーバのログを、NFSなどの共有ディスク(仮に/var/oldlogsとする)に集約する場合を考えてみる。まず、複数のサーバのログが同ファイル名のだと一箇所に集約したときに上書きされてしまう可能性があるので、例えば、/var/log/some/log-ホスト名の様にしなければならない。設定ファイル中で、ディレクティブ
olddir directoryでその共有ディスクに移動させる方法を思いつくかもしれない。/var/log/some/log-ホスト名 {
olddir /var/oldlogs
}
しかし、これは上手くいかない。というのは、logrotateでは、ローテート後のファイルは、元ファイルと同じデバイス上にしか置けない、という制限があるからだ。# cat /etc/logrotate.d/test
/var/log/some/log-ホスト名 {
olddir /var/oldlog
}
# ls /var/log/some
log-ホスト名
# logrotate -f /etc/logrotate.d/test
error: /etc/logrotate.d/test:3 olddir /var/oldlog and log file /var/log/some/log-ホスト名 are on different devices
#
これを回避するために、ローテート後に共有ディスクへのコピーを実行することを思いつくだろう。設定ファイル中でpostrotate/endscript ディレクティブを使えば実現できる。このディレクティブを用いると、mv直後にシェルスクリプトを実行させることができるためだ。
# cat /etc/logrotate.d/test
/var/log/some/log-ホスト名 {
rotate 4
postrotate
cp -p /var/log/some/log-ホスト名.1 /var/oldlog
endscript
}
# logrotate -f /etc/logrotate.d/test
# ls /var/log/some
log-ホスト名.1
# ls /var/oldlog
log-ホスト名.1 lost+found
#
しかし、これにもまだ問題が出る場合がある。ディレクティブcompressを使って、ログファイルを圧縮する場合だ。次の様にして上手くいくだろうか?
# cat /etc/logrotate.d/test
/var/log/some/log-ホスト名 {
rotate 4
compress
postrotate
cp -p /var/log/some/log-ホスト名.1.gz /var/oldlog
endscript
}
#
これは上手くいかない。
# ls /var/log/some/log-ホスト名* /var/log/some/log-ホスト名 # ls /var/oldlog/log-ホスト名* ls: /var/oldlog/log-ホスト名*: No such file or directory # logrotate -f /etc/logrotate.d/test cp: cannot stat `/var/log/some/log-ホスト名.1.gz': No such file or directory error: error running postrotate script for /var/log/some/log-ホスト名 # ls /var/log/some/log-ホスト名* /var/log/some/log-ホスト名.1.gz # ls /var/oldlog/log-ホスト名.* ls: /var/oldlog/log-ホスト名*: No such file or directory #なぜか?それは、実行タイミングにある。
logrotateは、まずmvし、postrotate/endscript ディレクティブのシェルスクリプトを実行した後、gzipで圧縮するため、シェルスクリプト実行時には、まだ*.1.gzというファイルは存在せず、圧縮前の*.1のままである。これは、
postrotate/endscript ディレクティブの代わりにlastaction/endscript ディレクティブを使えば解決できる。# cat /etc/logrotate.d/test
/var/log/some/log-ホスト名 {
rotate 4
compress
lastaction
cp -p /var/log/some/log-ホスト名.1.gz /var/oldlog
endscript
}
# ls /var/log/some/log-ホスト名*
/var/log/some/log-ホスト名
# ls /var/oldlog/log-ホスト名*
ls: /var/oldlog/log-ホスト名*: No such file or directory
# logrotate -f /etc/logrotate.d/test
# ls /var/log/some/log-ホスト名*
/var/log/some/log-ホスト名.1.gz
# ls /var/oldlog/log-ホスト名*
/var/oldlog/log-ホスト名.1.gz
#
このままでは、共有ディスクには一世代しか保存されない。また、一度コピーに失敗すると、復旧できない。これらを解決するには、dateextディレクティブとrsyncコマンドを用いる。# cat /etc/logrotate.d/test
/var/log/some/log-ホスト名 {
rotate 4
compress
dateext
lastaction
rsync -a /var/log/some/log-ホスト名-*.gz /var/oldlog
endscript
}
# ls /var/log/some/log-ホスト名*
/var/log/some/log-ホスト名
# ls /var/oldlog/log-ホスト名*
ls: /var/oldlog/log-ホスト名*: No such file or directory
# logrotate -f /etc/logrotate.d/test
# ls /var/log/some/log-ホスト名*
/var/log/some/log-ホスト名-20111104.gz
# ls /var/oldlog/log-ホスト名*
/var/oldlog/log-ホスト名-20111104.gz
#