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スクリプトの調査 […]