Apache/バーチャルホストのログをリモートのrsyslogに集約する
目次 |
syslog デーモンと logger コマンドの制限
Apache のアクセスログをログサーバ(syslog)で一括管理する方法としては、CustomLog の出力先を logger コマンドにパイプし syslog へ送る方法があるが、この方法には次のような問題点がある。
- syslog メッセージは 1024 バイト以下に規定されている。(RFC 3164 の規定による。)
- logger コマンドで 1024 バイト以上のメッセージを送ると、1024 バイトで区切られてしまい、1つのメッセージがバラバラになってしまう。
- syslog では、単一ファイルにログが記録されてしまうため、ログをローテーションさせるための方法を別に用意する必要がある。
- リモートの syslog サーバが止まってしまうと、ログを取りこぼしてしまう。
- syslog は UDP で動作するため、パケットの取りこぼしが発生する。
rsyslog と Perl スクリプトに入れ替える
これらの問題は syslog と logger コマンドの制限が原因になっているため、代替えのプログラムに変えることで解決する。 syslog は rsyslog に入れ替え、logger コマンドは syslog メッセージを送れる Perl スクリプトに入れ替える。
- rsyslog は 1024 バイト以上のメッセージを扱うことができる。
- Perl スクリプトでは 1024 バイト以上の syslog メッセージを送ることができる。
- rsyslog は、年・月・日ごとにログをローテーションさせる機能がある。
- リモートの syslog (rsyslog) サーバが止まっても、ローカルの rsyslog でログをスプールさせることができる。リモートログサーバが復旧するとスプールしていたログを自動的に送るので、ログの取りこぼしがない。
- rsyslog は UDP と TCP のどちらでも動作する。
バーチャルホストが増えた場合でも対応する方法
バーチャルホストごとにログを分けるには、バーチャルホストごとに syslog ファシリティを変えることで対応できる。 しかし、syslog ファシリティの数には限りがあるため、ファシリティでログを分けるには限界がある。(apache のアクセスログ用に使える syslog ファシリティは local0 から local7 までの 8 個。) syslog ファシリティとタグを組み合わせる方法もあるが、バーチャルホストを追加するたびに <VirtualHost> の CustomLog 設定と rsyslog の設定を編集しなければならなくなる。
rsyslog は、syslog メッセージの内容を元にログを仕分ける property replacer 機能があり、この機能を利用することでバーチャルホストごとにログを分けることができる。
大まかな方法は、バーチャルホスト名を含める LogFormat 形式を作成し、httpd.conf のみに CustomLog の設定をすることでログを1つにまとめて rsyslog に送る。(<VirtualHost> ごとに CustomLog を設定しない。) rsyslog ではバーチャルホスト名をキーに仕分け、バーチャルホストごとのファイルとして書き出す。
この方法では、バーチャルホストがいくら増えても CustomLog や rsyslog の設定を変更する必要がない。
さらに、ログを1つにまとめて rsyslog へ送る(パイプする)ので、syslog ファシリティを1つしか使わないうえ、httpd の子プロセスになるログのプロセスも1つですむ。 (<VirtualHost> ごとに CustomLog を設定すると、logger プロセスが設定した行数個 httpd の子プロセスとして起動する。)
設定
httpd.conf
Errorlog や CustomLog 設定を httpd.conf のみにする。
<VirtualHost> ごとに設定しない。全てコメントアウトする。
ErrorLog syslog:local1
LogLevel warn
LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vcombined
#CustomLog "|/usr/bin/logger -p local0.debug" vcombined
CustomLog |/usr/local/bin/apache_syslog.pl vcombined
- ErrorLog を syslog へ送るようにし、ファシリティ local1 に設定。
- LogFormat の先頭に ServerName[1] を意味する %v を追加し、vcombined という名前に定義。%v 以降は combined と同じにしている。
- CustomLog では、logger コマンドの代わりに次項の Perl スクリプトにパイプするようにし、LogFormat で定義した vcombined 形式で記録するよう指定する。
すべてのバーチャルホストのログを1つにまとめることになるが、特定のバーチャルホストだけ別処理をさせることもできる。方法は、別処理をしたい <VirtulHost> 内に CustomLog 設定をすればよい。 例えば、ログを保存しないようにするには次のようにする。 <VirtualHost *:80> ... CustomLog logs/access.log combined env=0 ... </VirtualHost> |
Perl スクリプト
ファシリティ local0、プライオリティ debug で syslog メッセージを送る Perl スクリプト。O'Reilly のサイトで紹介されていたスクリプトを一部編集。
#!/usr/bin/perl
use Sys::Syslog qw( :DEFAULT setlogsock );
setlogsock('unix');
openlog('apache', 'cons,pid', 'local0');
while ($log = <STDIN>) {
syslog('debug', $log);
}
closelog
rsyslog.conf (送信側)
Apache が動作しているマシンの rsyslog 設定。
#$ModLoad immark
*.info;mail.none;authpriv.none;cron.none;local0.none;local1.none -/var/log/messages
local0.debug @@192.168.100.166
local1.debug @@192.168.100.166
$WorkDirectory /var/spool/rsyslog
$ActionQueueFileName uniqName
$ActionQueueMaxDiskSpace 1g
$ActionQueueSaveOnShutdown on
$ActionQueueType LinkedList
$ActionResumeRetryCount -1
$MaxMessageSize 8k
3行目:ファシリティ local0 と local1 のメッセージが /var/log/messages に記録されないようにする。
5〜6行目:ログサーバ(例では 192.168.100.166)へ TCP 接続でメッセージを送る。
- @ だと UDP 接続、@@ で TCP 接続。
8〜13行目:ログサーバにメッセージを送れない時に、ローカルにスプールする設定。
- $ActionResumeRetryCount を -1 にすることで、ログの再送信を繰り返すようになる。デフォルトは 0 で再送信しない。
14行目:rsyslog の最大メッセージサイズを指定する。デフォルトは 2k (2KB) 。
rsyslog.conf (受信側)
Apache のログを受ける、ログサーバの rsyslog.conf 設定。
#$ModLoad immark
$ModLoad imudp.so
$UDPServerRun 514
$ModLoad imtcp.so
$InputTCPServerRun 514
$RepeatedMsgReduction off
$template MsgFormat, "%msg:2:$%\n"
$template httpd_access, "/var/log/rsyslog/%msg:F,32:2%/httpd_access_%$year%%$month%%$day%.log"
$template httpd_error, "/var/log/rsyslog/%fromhost-ip%/httpd_error_%$year%%$month%%$day%.log"
local0.debug -?httpd_access;MsgFormat
local1.debug -?httpd_error;MsgFormat
1行目:20分おきに挿入されるマークを記録しないよう immark モジュールをコメントアウト。
2〜5行目:リモートからのメッセージを受信するログサーバ機能を有効にする。あくまでもメッセージの受信を有効にするモジュールであって、TCP 送信を有効にするモジュールではない。TCP 送信はデフォルトの機能。
7行目:同じ内容のメッセージが繰り返し送られてきても last message repeated n times と省略しないようにする。
9〜11行目:メッセージの処理方法をテンプレート化して定義する。書式は Property Replacer に説明がある。
- "%msg:2:$%\n" の意味は、メッセージの先頭にスペースが1つ含まれているのを取り除く設定。メッセージの 2 文字目から最後まで($)を対象にするという意味。
- %msg:F,32:2% の意味は、区切り文字をスペースとして、2つ目のフィールドを抜き出す設定。
F | フィールドを抜き出す |
---|---|
F,32 | US-ASCII の 32 番目の文字=スペースを区切り文字にする。 |
2 | 2番目のフィールド |
13〜14行目:送られてきたメッセージをどのように(保存)するか、テンプレートを組み合わせる。[2]
ファシリティ.プライオリティ ?保存先;保存フォーマット ファシリティ.プライオリティ -?保存先;保存フォーマット
?保存先 の前に - を付けると非同期で保存するようになる。
参考ページ
- Mailing List Archive: rsyslog with apache and per vhost log
- Sending Apache httpd Logs to Syslog - O'Reilly Media
- mod_log_config - Apache HTTP サーバ
- rsyslog.conf configuration file rsyslog
脚注
- ↑ <VirtualHost> 内の ServerName ディレクティブで指定しているホスト名になる。
- ↑ Actions - rsyslog.conf rsyslog