Apache httpd 2.4.1 のコンパイル

Apache httpdの安定版のメジャーバージョンが上がって、Apache httpd 2.4.1 が 2012/02/21 に公開されました。2.2シリーズからの拡張の詳細は http://httpd.apache.org/docs/2.4/new_features_2_4.htmlにあります。その中で mod_lua が気になりました。組み込み用のスクリプト言語の「Lua」の名前だけは知っていましたが、文法や言語の特徴は全く知りませんでした。「The Programming Language Lua http://www.lua.org/」を見てみると小さく速い言語の様です。小さな言語好きの私は、さっそくコンパイルして試してみることにしました。

今回実験した環境は、64bit 版の Ubuntu 11.10 をインストールした非力な Intel Atom D510 (1.66GHz , 2Core / 4Thread) です。 このページで紹介している内容では /usr/local 以下のディレクトリのみを変更しているので、通常のUbuntuの環境には干渉せずに共存できるはずです。

今回はちょっと残念な結果となりましたが、今後に期待です。

Lua 5.1.4 のインストール

libluaをインストールすれば httpd のコンパイルは可能ですが、Luaのスクリプトの動作確認に使うので、スタンドアローン版のコンパイラ、インタプリタをインストールします。Ubuntu(11.10) の場合、Lua 5.1.4 が apt-get で簡単にインストールできます。

jun@atom:~$ sudo apt-get install lua5.1
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下のパッケージが新たにインストールされます:
  lua5.1
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 3 個。
147 kB のアーカイブを取得する必要があります。
この操作後に追加で 365 kB のディスク容量が消費されます。
取得:1 http://jp.archive.ubuntu.com/ubuntu/oneiric/main lua5.1 amd64 5.1.4-10 [147 kB]
147 kB を 0秒 で取得しました (201 kB/s)
未選択パッケージ lua5.1 を選択しています。
(データベースを読み込んでいます ... 現在 217920 個のファイルとディレクトリがインストールされています。)
(.../lua5.1_5.1.4-10_amd64.deb から) lua5.1 を展開しています...
man-db のトリガを処理しています ...
lua5.1 (5.1.4-10) を設定しています ...
update-alternatives: /usr/bin/lua (lua-interpreter) を提供するために 自動モード で /usr/bin/lua5.1 を使います。
update-alternatives: /usr/bin/luac (lua-compiler) を提供するために 自動モード で /usr/bin/luac5.1 を使います。

liblua5.1-dev

Apache で mod_lua をコンパイルする場合に必要な共有ライブラリ版のLuaライブラリ liblua5.1.so をインストールします。

jun@atom:~$ sudo apt-get install liblua5.1-dev
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
注意、'liblua5.1-dev' の代わりに 'liblua5.1-0-dev' を選択しています
以下の特別パッケージがインストールされます:
  autotools-dev libltdl-dev libtool
提案パッケージ:
  libtool-doc autoconf automaken gfortran fortran95-compiler gcj
以下のパッケージが新たにインストールされます:
  autotools-dev libltdl-dev liblua5.1-0-dev libtool
アップグレード: 0 個、新規インストール: 4 個、削除: 0 個、保留: 3 個。
668 kB のアーカイブを取得する必要があります。
この操作後に追加で 3,219 kB のディスク容量が消費されます。
続行しますか [Y/n]? y
取得:1 http://jp.archive.ubuntu.com/ubuntu/oneiric/main autotools-dev all 20110511.1 [44.7 kB]
取得:2 http://jp.archive.ubuntu.com/ubuntu/oneiric/main libltdl-dev amd64 2.4-2ubuntu1 [202 kB]
取得:3 http://jp.archive.ubuntu.com/ubuntu/oneiric/main liblua5.1-0-dev amd64 5.1.4-10 [120 kB]
取得:4 http://jp.archive.ubuntu.com/ubuntu/oneiric/main libtool amd64 2.4-2ubuntu1 [301 kB]
668 kB を 1秒 で取得しました (620 kB/s)
未選択パッケージ autotools-dev を選択しています。
(データベースを読み込んでいます ... 現在 217928 個のファイルとディレクトリがインストールされています。)
(.../autotools-dev_20110511.1_all.deb から) autotools-dev を展開しています...
未選択パッケージ libltdl-dev を選択しています。
(.../libltdl-dev_2.4-2ubuntu1_amd64.deb から) libltdl-dev を展開しています...
未選択パッケージ liblua5.1-0-dev を選択しています。
(.../liblua5.1-0-dev_5.1.4-10_amd64.deb から) liblua5.1-0-dev を展開しています...
未選択パッケージ libtool を選択しています。
(.../libtool_2.4-2ubuntu1_amd64.deb から) libtool を展開しています...
man-db のトリガを処理しています ...
autotools-dev (20110511.1) を設定しています ...
libltdl-dev (2.4-2ubuntu1) を設定しています ...
liblua5.1-0-dev (5.1.4-10) を設定しています ...
libtool (2.4-2ubuntu1) を設定しています ...

apr のインストール

httpd が依存している Apache Portable Runtime(何をするものかよく分かっていませんが)もインストールします。 apr-1.4.6.tar.gz と apr-util-1.4.1.tar.gz を http://apr.apache.org/から入手し、ビルドします。$HOME/lua というディレクトリを作り、それ以下で作業しました。

apr-1.4.6

root@atom:~/lua$ tar zxf apr-1.4.6.tar.gz
root@atom:~/lua$ cd apr-1.4.6
root@atom:~/lua/apr-1.4.6$ ./configure --prefix=/usr/local/apr-httpd/
root@atom:~/lua/apr-1.4.6$ make
root@atom:~/lua/apr-1.4.6$ sudo make install

/usr/local/apr-httpd 以下にインストールされました。

root@atom:/usr/local/apr-httpd# du .
12  ./bin
512 ./include/apr-1
516 ./include
312 ./build-1
8 ./lib/pkgconfig
2184  ./lib
3028  .

apr-util-1.4.1

root@atom:~/lua$ tar zxf apr-util-1.4.1.tar.gz
root@atom:~/lua$ cd apr-util-1.4.1
root@atom:~/lua/apr-util-1.4.1$ ./configure --prefix=/usr/local/apr-util-httpd/ \
    --with-apr=/usr/local/apr-httpd/
root@atom:~/lua/apr-util-1.4.1$ make
root@atom:~/lua/apr-util-1.4.1$ make install

/usr/local/apr-util-httpd 以下にインストールされました。

root@atom:/usr/local/apr-util-httpd# '''du .'''
12  ./bin
384 ./include/apr-1
388 ./include
8 ./lib/pkgconfig
2612  ./lib
3016  .

httpd-2.4.1 のビルド

ここまでの準備でやっとhttpd-2.4.1をコンパイルする環境が Ubuntu 11.10 上に整いました。configure のオプションは、「ローカルで mod_lua の機能を試す」事だけを念頭に置いた指定です。一般的に外向けに使用するWebサーバ用ではありません。

jun@atom:~/lua$ tar zxf httpd-2.4.1.tar.gz
jun@atom:~/lua$ cd httpd-2.4.1/
jun@atom:~/lua/httpd-2.4.1$ ./configure --prefix=/usr/local/apache24 \
  --with-apr=/usr/local/apr-httpd/ \
  --with-apr-util=/usr/local/apr-util-httpd/ --enable-lua
jun@atom:~/lua/httpd-2.4.1$ make
jun@atom:~/lua/httpd-2.4.1$ sudo make install

インストールしたmod_lua.soを調べてみる。mod_lua.so も liblua5.1.so も小さいことがわかります。libphp5.so は 8MB 以上なので 20分の1 程度です。

jun@atom:/usr/local/apache24/modules$ ls -l mod_lua.so 
-rwxr-xr-x 1 root root 184927 2012-02-25 00:07 mod_lua.so

jun@atom:/usr/local/apache24/modules$ ldd mod_lua.so 
	linux-vdso.so.1 =>  (0x00007fff12cda000)
	liblua5.1.so.0 => /usr/lib/x86_64-linux-gnu/liblua5.1.so.0 (0x00007fc3ad5ee000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc3ad3d1000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc3ad031000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc3acdad000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc3acba9000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fc3ada4d000)

jun@atom:/usr/lib/x86_64-linux-gnu$ ls -l liblua5.1.so*
lrwxrwxrwx 1 root root     18 2011-07-27 20:44 liblua5.1.so -> liblua5.1.so.0.0.0
lrwxrwxrwx 1 root root     18 2011-10-19 00:38 liblua5.1.so.0 -> liblua5.1.so.0.0.0
-rw-r--r-- 1 root root 183792 2011-07-27 20:44 liblua5.1.so.0.0.0

jun@atom:/usr/lib/x86_64-linux-gnu$ ldd liblua5.1.so
	linux-vdso.so.1 =>  (0x00007fffd8575000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0ccbaff000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0ccb8fb000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0ccb55b000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f0ccbfd3000)

Apache httpd-2.4.1 の起動と mod_lua のテスト

Apache httpd の設定

Apache 2.4.1 を /usr/local/apache24 以下のディレクトリにインストールしたので、/usr/local/apache24/conf/ にある httpd.conf を書き換えます。Ubuntuに干渉しないように ポート8880で起動することにします。httpd.conf の設定方法だけでも分厚い書籍が書けてしまうので、ここでは mod_lua を試すだけの最小限の設定だけ行うことにします。


まずオリジナルの httpd.conf をコピーして httpd.conf.2.4.1 に保存しておきます。多くのファイルに分散しているDebian系のLinuxと異なり、自分でビルドしたApacheでは、設定ファイルはhttpd.conf の1つだけです。

jun@atom:~$ cd /usr/local/apache24/conf
jun@atom:/usr/local/apache24/conf$ sudo cp httpd.conf httpd.conf.2.4.1
jun@atom:/usr/local/apache24/conf$ sudo vi httpd.conf

httpd.conf の52行目で待受けポートを 80 から 8880 に変更します。

     52 Listen 8880

httpd.conf の106行目のコメント記号「#」を削除して、mod_lua を使うように指定します。

    106 LoadModule lua_module modules/mod_lua.so

<IfModule mime_module> のブロック内に拡張子 lua を指定します。これで 拡張子が「.lua」のファイルの場合、Apache はフィル内の handle 関数を実行します。ここでは 388行目の空行に追加しました。

    388     AddHandler lua-script .lua

Apache httpd 2.4.1 の起動

jun@atom:~$ sudo /usr/local/apache24/bin/apachectl start

ブラウザでアクセス

http://localhost:8880/または別マシンからアクセスする場合は http://IPアドレス:8880/( うちの場合 http://172.18.21.100:8880/)でアクセスすると以下のように表示されます。

It works!

はじめての Lua

実際にLuaのスクリプトを動かしてみます。次のファイルを /usr/local/apache24/htdocs に置いて、http://localhost:8880/hi.luaでアクセスします。

function handle(r)
    r.content_type = "text/plain"
    r:write "Hi, I'm Lua.\n"
end

動作しました。

Hi, I'm Lua.

Apache のサンプル

Apacheの mod_lua のドキュメントの example.lua を試してみました。

require "string"

function handle(r)
  r.content_type = "text/plain"
  r:puts("Hello Lua World!\n")

  if r.method == 'GET' then
    for k, v in pairs( r:parseargs() ) do
      r:puts( string.format("%s: %s", k, v) )
    end
  elseif r.method == 'POST' then
    for k, v in pairs( r:parsebody() ) do
      r:puts( string.format("%s: %s", k, v) )
    end
  else
    r:puts("unknown HTTP method " .. r.method)
  end
end

GET のテスト

「 http://localhost:8880/example.lua?a=aa&b=bb&c=cc 」でアクセスした時のレスポンス。

Hello Lua World!
a: aac: ccb: bb

順序は違いますが、正しく受け取ることができました。

POST のテスト

POSTのテストは以下のようなファイルを作成し、ブラウザで開きました。

<html><head>
<title>mod_lua test</title>
</head>
<body>
<form action='http://localhost:8880/example.lua' method='post'>
 <fieldset>
 <input type=submit name='write' value='write' ><br />
 <textarea name='msg'></textarea>
 </fieldset>
</form>
</body></html>

「parsebodyがない」というエラーになります。

Hello Lua World! Error!
/usr/local/apache24/htdocs/example.lua:12: attempt to call method 'parsebody' (a nil value)

mod_lua の状況

ソースを調べると httpd-2.4.1/modules/lua/lua_request.c に parsebody に対応するコードがありません。req_parseargs と同じように req_parsebody があるはずで、req_parseargs が関数内で使っている ap_args_to_table() から検索するとap_body_to_table に関する記述が見つかります。include/ap_mmn.h 内には次のような記述があります。

 *20100609.0 (2.3.6-dev)  Dropped ap_body_to_table due to missing constraints.

理由は見つけられませんでしたが、「制限の欠如のため削除」したようです。セキュリティ関連でしょうか?また、include/httpd.h にも同じような内容のコメントが見つかります。

    /** For ap_body_to_table(): parsed body */
    /* XXX: ap_body_to_table has been removed. Remove body_table too or
     * XXX: keep it to reintroduce ap_body_to_table without major bump? */
    apr_table_t *body_table;

POSTのデータを受け取ることができなければ、Luaでちゃんとしたアプリケーションを作るのは現時点では無理そうです。mod_lua は 2.4.1 でも「Experimental」となっています。 本格的に利用するには、まだ早いようです。


Lua は文法がコンパクトで分かりやすく、バイナリのサイズも小さいのでApacheに組み込まれた結果、もっと知名度が上がれば将来有望な言語 (ゲームなどへの組み込み言語としては十分実績があるかもしれませんが) になるのではと思います。 ちゃんと使えるようになるのが楽しみです。 それまでスタンドアロンの 「lua」コマンドで経験値を上げておこうかと。

このページの目次