logrotateスクリプトの調査
Linuxでログファイルを一定期間ごとで切り出し、世代管理を行ってくれるlogrotate。
logrotateでは、単にログをローテションするだけではなく、ローテションの際にスクリプトを動作させることが可能となっています。
それらのスクリプトは、/etc/logrotate.confや、インクルードされる/etc/logrotate.d/hogehogeといったファイルに定義します。
スクリプトを動作させることが可能なタイミングは以下の4つあります。
firstaction
ログローテーションプロセスの1番最初prerotate
ログファイルをローテーションする前postrotate
ログファイルをローテションした後lastaction
ログローテーションプロセスの1番最後
# 正直、firstactionとprerotate、postrotateとlastactionの違いはあまりよく分かっていません。
これらのタイミングで、何らかの処理を行うことが可能ですが、その処理の中にはログファイル自身を扱う処理も行えます。
ログファイル自身を扱うためには、その時点でのログファイルの状態(圧縮されたのか、ローテションされただけなのか、まだ何もされていないのか)などが気になります。
調べては見ましたが、特にまとまった情報も無いようですし、OSやlogrotatedのバージョンによっても挙動が変化するそうなので、今回は自分が使う環境で色々調査してみました。
ローテーション前後のファイル名
ログローテーションを実施した際のファイル名がどうなるのかおさらいしておきます。
apache2のログファイル(/var/log/httpd/access_log)を例に挙げます。
- ローテーション前
access_log - ローテーション後
access_log.1 - 圧縮後
access_log.1.gz
このように、ファイル名が推移していくわけです。
問題は、firstactionからlastactionのそれぞれのどの段階でファイル名が変わっているかの情報が少ないこと。
スクリプトの引数に渡されるファイル名
実は、スクリプトの中で$1という変数を使用して、スクリプトに渡されるファイル名を受け取ることができます。
具体的には次のようなスクリプトが書けます。
/var/log/httpd/*log {
daily
compress
...(snip)...
prerotate
for infile in $1; do
echo $1
done
endscript
}
/var/log/httpd/*logの各々に対してforでループを回しているわけです。
しかし、この$1もやっかいなのです。
firstactionからlastactionのそれぞれの段階で、渡される引数が異なっているようで、やっかいな代物。
検証してみる
検証環境
- CentOS 6.3
(これだけかよ!)
スクリプトの準備
上記で示した2点、「各時点でのファイル名」と「各時点での$1引数」について、調べてみることにしました。
そのために、以下の様なlogrotateスクリプトを用意します。
元は、/etc/logrotate.d/httpdファイルで、それを修正したものになります。
/var/log/httpd/*log {
daily
rotate 100
nodateext
compress
nodelaycompress
ifempty
missingok
sharedscripts
firstaction
echo "firstaction start" > /root/logrotate_log
for infile in $1; do
echo " \$1 is $infile" >> /root/logrotate_log
done
[ -f /var/log/httpd/access_log ] && echo " exist access_log" >> /root/logrotate_log
[ -f /var/log/httpd/access_log.1 ] && echo " exist access_log.1" >> /root/logrotate_log
[ -f /var/log/httpd/access_log.1.gz ] && echo " exist access_log.1.gz" >> /root/logrotate_log
echo "firstaction end" >> /root/logrotate_log
endscript
prerotate
echo "prerotate start" >> /root/logrotate_log
for infile in $1; do
echo " \$1 is $infile" >> /root/logrotate_log
done
[ -f /var/log/httpd/access_log ] && echo " exist access_log" >> /root/logrotate_log
[ -f /var/log/httpd/access_log.1 ] && echo " exist access_log.1" >> /root/logrotate_log
[ -f /var/log/httpd/access_log.1.gz ] && echo " exist access_log.1.gz" >> /root/logrotate_log
echo "prerotate end" >> /root/logrotate_log
endscript
postrotate
/sbin/service httpd reload > /dev/null 2>/dev/null || true
echo "postrotate start" >> /root/logrotate_log
for infile in $1; do
echo " \$1 is $infile" >> /root/logrotate_log
done
[ -f /var/log/httpd/access_log ] && echo " exist access_log" >> /root/logrotate_log
[ -f /var/log/httpd/access_log.1 ] && echo " exist access_log.1" >> /root/logrotate_log
[ -f /var/log/httpd/access_log.1.gz ] && echo " exist access_log.1.gz" >> /root/logrotate_log
echo "postrotateend" >> /root/logrotate_log
endscript
lastaction
echo "lastaction start" >> /root/logrotate_log
for infile in $1; do
echo " \$1 is $infile" >> /root/logrotate_log
done
[ -f /var/log/httpd/access_log ] && echo " exist access_log" >> /root/logrotate_log
[ -f /var/log/httpd/access_log.1 ] && echo " exist access_log.1" >> /root/logrotate_log
[ -f /var/log/httpd/access_log.1.gz ] && echo " exist access_log.1.gz" >> /root/logrotate_log
echo "lastaction end" >> /root/logrotate_log
endscript
}
これでやっていることは、次の通りです。
firstactionからlastactionの各段階で実施していることは同じです。
各段階の、最初と最後で
echo "lastaction start" >> /root/logrotate_log echo "lastaction end" >> /root/logrotate_log
とすることで、各段階の最初と最後と示します。
次に、
for infile in $1; do echo " \$1 is $infile" >> /root/logrotate_log done
とすることで、$1にどのような値が含まれているかを表示します。
さらに、
[ -f /var/log/httpd/access_log ] && echo " exist access_log" >> /root/logrotate_log [ -f /var/log/httpd/access_log.1 ] && echo " exist access_log.1" >> /root/logrotate_log [ -f /var/log/httpd/access_log.1.gz ] && echo " exist access_log.1.gz" >> /root/logrotate_log
とすることで、この段階で生成されているログファイル名を表示します。
結果を見る
では、このようにして修正した、/etc/logrotate.d/httpdスクリプトをlogrotatedに食わせてみます
# logrotate /etc/logrotate.d/httpd
これでOK。
結果は、/root/logrotate_logに出力されます。
結果はこんな感じになるでしょう。
firstaction start $1 is /var/log/httpd/access_log $1 is /var/log/httpd/error_log exist access_log firstaction end prerotate start $1 is /var/log/httpd/access_log $1 is /var/log/httpd/error_log exist access_log prerotate end postrotate start $1 is /var/log/httpd/*log exist access_log.1 firstaction end lastaction start $1 is /var/log/httpd/*log exist access_log.1.gz lastaction end
結構、意外な結果になったかと思います。
まとめるとこんな感じですね。
| ファイル名 | $1の引数 | |
|---|---|---|
| firstaction | access_log | /var/log/httpd/access_log /var/log/httpd/error_log |
| prerotate | access_log | /var/log/httpd/access_log /var/log/httpd/error_log |
| postrotate | access_log.1 | /var/log/httpd/*log |
| lastaction | access_log.1.gz | /var/log/httpd/*log |
ただ、この結果、色々思うところがあってですね。。。
delaycompressだったらどうなるのかとか、sharedscriptじゃなかったらとか。。。
気が向けばこれらもまとめるかもしれません。

1件の返信
[…] 参考: logrotateスクリプトの調査 […]