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 #