Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

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に接続してエラーログが振り分けられるかをテストしました

http://hoge.com/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

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

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした