mod_vhost_alias
Apacheのmod_vhost_aliasのVirtualDocumentRootは非常に便利で
一つの設定でapacheの再起動なしに複数のVirtualHostを運用する事ができます。
しかし、mod_vhost_aliasにはその特性上からかいくつか欠点があり、そのうちの一つとして
「アクセスログ、エラーログがVirtualHost単位で分割できない」
という問題があります。
最悪アクセスログに関してはLogFormat
にて%v
を指定する事でVirtualHostのServerNameをログに出力させる事ができるので、フィルターなりを行うとなんとか取得可能なのですが、エラーログについてはApacheの仕様でLogFormat
を変更できないという事がありどうしようもない状態でした。
今回はmod_mrubyを使用してmod_vhost_aliasのどうしようもないエラーログをVirtualHost単位に出力させる方法を検証しました。
mod_mruby
mod_mrubyは@matsumotory氏が開発を始めたApacheの拡張モジュールです。mrubyでApacheのモジュールが書けちゃいます。
(mod_mruby) https://github.com/matsumoto-r/mod_mruby
(document) https://github.com/matsumoto-r/mod_mruby/wiki
mod_mrubyのインストール
# debian
apt-get install ruby bison libhiredis-dev
# centos
yum install ruby bison hiredis-devel
cd /usr/local/src
git clone git://github.com/matsumoto-r/mod_mruby.git
cd mod_mruby
sh build.sh
make install
modules/mod_mruby.soが作成され、httpd.confに
LoadModule mruby_module modules/mod_mruby.so
の行が追加されます。
apacheの設定
<VirtualHost *:80>
VirtualDocumentRoot /home/%0/public
mrubyInsertFilterMiddle /path/to/vhost-log.rb
</VirtualHost>
mod_vhost_aliasは、上記のような設定です。
ちなみに、ここでErrorLog ディレクティブを設定しちゃうと、mrubyでの別ファイルへのerror_log出力は動かなくなったので記述はしないようにしています。
mrubyInsertFilterMiddleという部分はフックするタイミングで、続いて、実行するmrubyスクリプトのパスを記述します。
今回のエラーログ分割では、ここでmrubyInsertFilterMiddle
としなければうまく動きませんでした。
具体的にはmrubyLogTransactionMiddle
ですと、うまくふりわけきれないような挙動となりました。(なんでだろう・・)
vhost-log.rb
# coding: utf-8
r = Apache::Request.new
unless Dir.exist?("/usr/local/apache2/logs/" + r.hostname) then
Dir.mkdir("/usr/local/apache2/logs/" + r.hostname , 0705)
end
r.error_log_into "/usr/local/apache2/logs/" + r.hostname + "/error_log"
Apache::return(Apache::OK)
r.error_log_into というメソッドにてApacheのエラーログを任意のファイルに書き出す事ができます。(@matsumotory氏にtwitterにて教えて頂きました)
また r.hostname メソッドにて接続中のServerNameを取得し、その値に応じてディレクトリを作成しログの出力先を変更しています。
テスト
ここでApacheを再起動。
エラーが出るようなtest.cgiに接続してエラーログが振り分けられるかをテストしました
cat /usr/local/apache2/logs/hoge.com/error_log
[Tue Jan 06 19:41:37 2015] [error] [client 192.168.56.1] (13)Permission denied: exec of '/home/hoge.net/public/test.cgi' failed
[Tue Jan 06 19:41:37 2015] [error] [client 192.168.56.1] Premature end of script headers: test.cgi
cat /usr/local/apache2/logs/fuga.com/error_log
[Tue Jan 06 19:43:42 2015] [error] [client 192.168.56.1] (13)Permission denied: exec of '/home/fuga.com/public/test.cgi' failed
[Tue Jan 06 19:43:42 2015] [error] [client 192.168.56.1] Premature end of script headers: test.cgi
ばっちり!
おわりに
まだ検証不足ではありますが、mod_vhost_aliasの問題を一つ解決できました。
僕はC言語はまったくできないですし、rubyもペーペーですがそれでも簡単に実装でき驚いています。
今回はエラーログの振り分けがなんとかならないか調べていてmod_mrubyにたどり着きましたが、
mod_mrubyのドキュメントを読めば読むほどその可能性にわくわくしてきました。
これからいろんなところで使ってみたいと思います。
参考
- mod_mruby ngx_mruby Advent Calendar 2014
- Apacheによるバーチャルホスト構築レシピ mod_mruby編 アクセスログの出力はこちらが非常に参考になりました