Apache上でRailsアプリを動かすPassengerを使ってみたよ(その1)

Apache上でRedmineを動かそうとしたのですが、設定などいろいろ面倒なところもあります。
ちょうど、Passengerというもの知ったので、試してみることにしました。
Apache上でRuby on Railsアプリケーションを動かす/Passenger(mod_rails for Apache)の利用 — Redmine.JP

  • Apache単独でRailsアプリケーションを実行可能です。Apacheのモジュールとして実装されており、別途デーモンを起動する必要がありません。tcpポートも使いません。
  • Railsアプリケーションのデプロイが簡単になります。ファイルをアップロードするだけ。ほぼPHP感覚です。
  • サーバのメモリを節約できます。Railsインスタンスは必要なタイミングで生成します。また、一定時間アクセスがなければインスタンスを終了させます。


Apache単独でRailsアプリケーションを実行できて、デプロイが簡単になる。
いい感じですね。

インストール

gemで簡単にインストールできます。

# gem install passenger


次にApacheモジュールのビルドとインストールをします。

# passenger-install-apache2-module

対話形式で処理が続きます。


足らないソフトウェアなどがあると、apt等でインストールするためのコマンドを示してくれます。
親切ですね。

* Apache 2 development headers... not found
* Apache Portable Runtime (APR) development headers... not found
* Apache Portable Runtime Utility (APU) development headers... not found

Some required software is not installed.
But don't worry, this installer will tell you how to install them.

Press Enter to continue, or Ctrl-C to abort.

                                                                                      • -

Installation instructions for required software

* To install Curl development headers with SSL support:
Please run apt-get install libcurl4-openssl-dev or libcurl4-gnutls-dev, whichever you prefer.

* To install Apache 2 development headers:
Please run apt-get install apache2-prefork-dev as root.

* To install Apache Portable Runtime (APR) development headers:
Please run apt-get install libapr1-dev as root.

* To install Apache Portable Runtime Utility (APU) development headers:
Please run apt-get install libaprutil1-dev as root.


必要なソフトウェアもインストールし、Apacheモジュールをビルドしているとコンパイルでエラー発生。

cd /usr/lib/ruby/gems/1.8/gems/passenger-3.0.2/usr/bin/ruby1.8 /usr/bin/rake apache2:clean apache2 RELEASE=yes# /usr/bin/ruby1.8 /usr/bin/rake apache2:clean apache2 RELEASE=yes(in /usr/lib/ruby/gems/1.8/gems/passenger-3.0.2)rm -rf ext/common/libboost_oxt.a ext/common/libboost_oxtrm -rf ext/common/libpassenger_common.a ext/common/libpassenger_commonrm -f agents/PassengerWatchdog agents/PassengerLoggingAgentrm -rf ext/apache2/module_libboost_oxt.a ext/apache2/module_libboost_oxtrm -rf ext/apache2/module_libpassenger_common.a ext/apache2/module_libpassenger_commonrm -rf ext/apache2/Configuration.o ext/apache2/Bucket.o ext/apache2/Hooks.o ext/apache2/mod_passenger.o ext/apache2/mod_passenger.so agents/PassengerHelperAgentmkdir -p ext/apache2/module_libpassenger_commong++ -Iext -Iext/common -Iext/libev -fPIC -fvisibility=hidden -DVISIBILITY_ATTRIBUTE_SUPPORTED -Wno-attributes -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE -I/usr/include/apr-1.0 -I/usr/include/apr-1.0 -I/usr/include/postgresql -I/usr/include/mysql -DLINUX=2 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_REENTRANT -I/usr/include/apr-1.0 -I/usr/include/mysql -I/usr/include/openssl -I/usr/include/postgresql -I/usr/include/xmltok -pthread -I/usr/include/apache2 -D_REENTRANT -I/usr/local/include -DHASH_NAMESPACE="__gnu_cxx" -DHASH_NAMESPACE="__gnu_cxx" -DHASH_FUN_H="" -DBOOST_SP_USE_PTHREADS -Wall -g -DPASSENGER_DEBUG -DBOOST_DISABLE_ASSERTS -o ext/apache2/module_libpassenger_common/aggregate.o -c ext/apache2/module_libpassenger_common/aggregate.cppIn file included from ext/common/Utils/VariantMap.h:33, from ext/common/AgentBase.h:30, from ext/common/AgentBase.cpp:44,
from ext/apache2/module_libpassenger_common/aggregate.cpp:6:
ext/common/MessageChannel.h: In member function ‘bool Passenger::MessageChannel::readRaw(void*, unsigned int, long long unsigned int*)’:
ext/common/MessageChannel.h:583: error: ‘llroundl’ was not declared in this scope
ext/common/MessageChannel.h:590: error: ‘llroundl’ was not declared in this scope
rake aborted!
Command failed with status (1): [g++ -Iext -Iext/common -Iext/libev -fPIC -...]

(See full trace by running task with --trace)


エラーの内容からすると、MessageChannel.h中のllroundlという関数が未定義らしいデス。
llroundlが何ものか調べたところ以下のようなページ発見。
C言語関数辞典 - llround, llroundf, llroundl

llroundl 関数は,long double 型の引数 x を最も近い整数値に丸め,結果を long long 型で返します.引数がちょうど中間にある場合は,その時点の丸め方向にかかわらず 0 から遠い方向を選びます.

いわゆる四捨五入というやつです。
C99のmath.hに入っている関数らしいですが、g++には含まれてないのかもしれないですね。
今回は玄箱ProのDebian lenny上でコンパイルしたため、もしかするとARM用のコンパイラだと対応してなかったのかもしれません。


ただの値をまるめる処理のようなので、llroundlを使わない形式にMessageChannel.hを書き換えました。

  • Before
    bool readRaw(void *buf, unsigned int size, unsigned long long *timeout = NULL) {
        if (timeout != NULL) {
            unsigned long long t = *timeout * 1000;
            unsigned int ret;
            try {
                ret = Passenger::readExact(fd, buf, size, &t);
                #ifdef __NetBSD__
                    *timeout = llround((double) t / 1000);
                #else
                    *timeout = llroundl((long double) t / 1000);
                #endif
                return ret == size;
            } catch (...) {
                #ifdef __NetBSD__
                    *timeout = llround((double) t / 1000);
                #else
                    *timeout = llroundl((long double) t / 1000);
                #endif
                throw;
            }   
        } else {
            return Passenger::readExact(fd, buf, size) == size;
        }   
    }   
  • After
    bool readRaw(void *buf, unsigned int size, unsigned long long *timeout = NULL) {
        if (timeout != NULL) {
            unsigned long long t = *timeout * 1000;
            unsigned int ret;
            try {
                ret = Passenger::readExact(fd, buf, size, &t);
                #ifdef __NetBSD__
                    *timeout = llround((double) t / 1000);
                #else
                    *timeout = (long long)((long double) t / 1000 + 0.5);
                #endif
                return ret == size;
            } catch (...) {
                #ifdef __NetBSD__
                    *timeout = llround((double) t / 1000);
                #else
                    *timeout = (long long)((long double) t / 1000 + 0.5);
                #endif
                throw;
            }   
        } else {
            return Passenger::readExact(fd, buf, size) == size;
        }   
    } 


llroundl(hogehoge)なところを(long long)(hogehoge + 0.5)にしただけですね。
一応、これでコンパイルは無事通りました。