今回は、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: ローテート後の後処理

ログローテート後に実行するスクリプトを指定します。

postrotateendscript の間に複数書くことができます。

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 の世界では標準になっているテキストベースのマニュアルはすごいエコシステムですよね。


 

 

zaturendo

中小企業社内SE。

0件のコメント

コメントを残す

アバタープレースホルダー

メールアドレスが公開されることはありません。 が付いている欄は必須項目です