今回は、Logrotate についての覚書です。
自身で作成した Web アプリケーションで、ログを残すようにしている場合で、ログローテーションの設定をしていないと、気がつけばログファイルが巨大になっていた、なんてことがあります。
で、このファイルをログローテーションしようと思い色々作業したのですが、その際に得た知識を共有しておこうと思います。
logrotate について
アプリケーションの動作状況を記録するために、ログファイルというテキストファイルに情報を書き出すようにすることが多いと思います。
また、ログファイルにログを追記していく形になるので、ログの出力頻度にもよりますが、漫然と放っておいたりすると、あっという間に大きなファイルサイズに膨れ上がっていることになります。
このようなとき考えられるのは、
- 一定期間でログファイルを作成しなおす
- ログファイルを複数世代残す場合、ファイルを圧縮する
などですが、これをアプリケーション単位で実装するのは決して面倒ではないですが、アプリケーションごとにマチマチな実装になり、統一感がなくなることは想像に難くありません。
そこで、UNIX の世界では logrotate という便利なユーティリティーがあります。このユーティリティーが UNIX 共通のログファイルの管理を提供してくれるので、アプリケーション作成者は、ログのローテーションのことまで考えなくても良いようになっています。
logrotate はどのようにして動いているのか
多くのディストリビューションでは、/etc/cron.daily/logrotate
で、スケジューリングされて実行されています。
時間単位で頻繁にローテートする必要があるときには、/etc/cron.hourly
にスクリプトを置きます。
logrotate.conf
メインのログローテートの設定は、/etc/logrotate.conf
にあります。
ここには、logrotate に関するデフォルトの設定が置いてあり、中のコメントには詳細が記載されています。さらに詳細な情報は、マニュアルを参照します。
このファイル中、いちばん肝心なのは以下の一行です。
include /etc/logrotate.d
/etc/logroatate.d
にはアプリケーション固有のログローテートに関する設定が置かれているディレクトリになっており、ここで各ログローテーションに関する設定をインクルードしています。
ようするに /etc/logroatate.d
に設定ファイルをおいておけば、あとは logrotate
がよしなに図ってくれる、というわけです。
ログローテート設定ファイル
ログローテートの設定ファイルでは、対象となるログファイルのリストに続いて、中括弧で囲まれたコマンドセットで、定義されています。
通常は一つのファイルに一つのログファイルブロックが定義されていますが、複数ブロックも定義可能なだけでなく、logrotate.conf
にログファイルブロックを追加することもできます。
一つのログファイルブロックに対象となるログファイルを複数列挙するには、ワイルドカードを使用したり、空白で区切ってログファイルを指定することで可能になります。
/var/foo/*.log /var/bar/log.txt {
rotate 14
daily
compress
delaycompress
sharedscripts
postrotate
/usr/sbin/apachectl graceful > /dev/null
endscript
}
コマンド
設定のコマンドに関しての詳細は、マニュアルの DIRECTIVES の項目に記載されています。
man logrotate
ここでは主要なものについて説明します。
rotate
: ローテート回数
logrotate
が、古いログの削除前に、何個ののログファイルを残すのかを指定。
次の例は、4つのログファイルを常に保持する場合。
rotate 4
size
: ログファイルのサイズ
サイズに指定したファイルサイズより大きくなった時にログローテートを実行します。
サイズの単位は以下のように指定できます。
size 100k
size 100M
size 100G
compress
: ログファイルの圧縮
ログファイルを、gzip
で圧縮します。
compress
ちなみに、ログファイルを圧縮したくない場合は、ncompress
コマンドを使用します。
 ;
delaycompress
: 圧縮を先延ばしする
ログファイルを次回のログローテート時に圧縮したい場合は、delaycompress
を使用します。これによって、直近にローテートされたログファイルは圧縮されず、それよりも前にローテートされたファイルは圧縮されている状態になります。
myapp.log # 現在のログファイル
myapp.log.1 # 直近にローテートされたログファイル
myapp.log.2.gz # より前にローテートされたログファイル
myapp.log.3.gz # 更により前に(ry
:
ただし、delaycompress
を使用する場合には、同時に compress
を指定する必要があります。
compress
delaycompress
postrotate
: ローテート後の後処理
ログローテート後に実行するスクリプトを指定します。
postrotate
~ endscript
の間に複数書くことができます。
postrotate
/usr/sbin/apachectl restart > /dev/null
endscript
他のコマンド
copytruncate
- 古いログファイルを移動して、(任意で)新しいログファイルを作成する代わりに、コピーを作成後に元のログファイルをそのままサイズを0にします。
ifempty
- ログファイルが空でもローテートする(既定)。
missingok
- ログファイルがない場合、エラーメッセージを出さずに次へ進む。
nomissinok
- ログファイルがない場合は、エラーメッセージを出す(既定)。
notifempty
- ログファイルが空の場合はローテートしない。
su
user group- デフォルトのユーザーとグループ(root, adm)を使用せずに、ここで指定されたユーザー、グループで設定されたログファイルをローテーションします。
ログローテートの手動実行
ログローテートを手動で実行したい、とか、テストしてみたい場合は次のようにします。
logrotate -vdf /etc/logrotate.d/myapp.conf
myapp.conf
は実行したい対象のログローテート設定ファイルを指定します。
このコマンドのオプションの説明は以下のとおりです。
-d, --debug
- デバッグモードで実行します。ログローテートしたとみなして実行します。実際にログローテートは行われません。
-f, --force
- 強制的にログローテーションを実行します。
-v, --verbose
- 詳細なメッセージを出力します。
以上から、
logrotate -vdf /etc/logrotate.d/myapp.conf
で、動作を確認してエラーをチェックし、
logrotate -vf /etc/logrotate.d/myapp.conf
で、実際にローテーションを実行する、というのは良い方法だと思われます。
ログファイルのパーミッション
上記を踏まえて、ここでは実際に、自身が作成したWeb アプリケーションのログファイルをローテートしてみようと思います。
例えば、ls -alh /var/log/myapp*
すると次のようになっています。
-rw-r--r-- 1 www-data www-data 25M Aug 19 13:48 myapp.log
このログファイルは、オーナーとグループは共に www-data
で、モードは、640
になっていて、無知な私は次のようなログローテートの設定ファイルを作成しました。
# /etc/logrotate.d/myapp
/var/log/myapp.log {
rotate 14
daily
compress
notifempty
delaycompress
copytruncate
}
コマンドの内容は、前項までの例でわかると思うのですが、このログローテートファイルを強制実行してみると、次のようなエラーを吐きます。
sudo logrotate --force /etc/logrotate.d/myapp
error: skipping "/var/log/myapp.log" because parent directory has insecure permissions (It's world writable or writable by group which is not "root") Set "su" directive in config file to tell logrotate which user/group should be used for rotation.
エラーメッセージによると、
親ディレクトリのパーミッションが
root
でないグループでも読み書き可能な安全ではないパーミッションなので、処理をスキップしました。
とあります。さらに、
ログローテート設定ファイルの中で、
su
コマンドを使って logrotate にローテーションにどのユーザー/グループを使用するのか伝えろ。
とのことです。
で、結局色々やってみた結果、以下のような方法で問題を解決しています。
ログローテートの設定ファイルに、su
コマンドを追加します。
/var/log/diaper.log {
su www-data www-data
rotate 90
daily
compress
missingok
notifempty
delaycompress
copytruncate
}
一応これでログファイルのローテートが出来るようになりました。
実際には、アプリケーション専用のログファイルディレクトリにログを残すように設定するほうがいいかもしれませんね。
まとめ
ログローテートの設定って、そんなに頻繁にするわけではないので毎回調べてやっていたのですが、今回はより詳しく知れたような気がします。
今回はWebで検索した海外のサイトを参考にしましたが、そこはやはり Linux (UNIX) の世界では、マニュアルにほぼすべての情報があるというのを実感させられます。Windows のヘルプファイルは余り見る気しませんが、UNIX の世界では標準になっているテキストベースのマニュアルはすごいエコシステムですよね。
0件のコメント