LoginSignup
7

More than 5 years have passed since last update.

posted at

Apacheのmod_vhost_aliasでログをバーチャルホスト単位で分割できない問題をmod_mrubyで解決する

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のドキュメントを読めば読むほどその可能性にわくわくしてきました。
これからいろんなところで使ってみたいと思います。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
7