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

前回の更新からだいぶ時間が経ってしまいましたね。
設定自体は済んでいたのですが、まとめるのが面倒くさいので先延ばしにしてしまいました。


さて、前回まででコンパイルも通りインストールは完了していました。
今回はApacheの設定ファイルへの設定を行います。


debian(lenny)の場合だとaptでインストールしたapacheの設定ファイルは以下のような感じになっています。
(squeezeでも同じです。)

$ ls /etc/apache2/
apache2.conf
conf.d
envvars
httpd.conf
mods-available
mods-enabled
ports.conf
sites-available
sites-enabled

debianの場合はmodを追加する場合はmods-available以下に各modごとの設定を記述したファイルを配置します。
そして、そのmodを有効にする場合はmods-enabled以下にmods-available以下に配置した設定ファイルへのシンボリックリンクを張ります。

passenger.loadの配置

以下のファイルを配置します。

  • /etc/apache2/mods-available/passenger.load

内容:

LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-1.0.1/ext/apache2/mod_passenger.so

passenger.loadにはmodのロードに関する部分のみ記述します。

passenger.confの配置

以下のファイルを配置します。

  • /etc/apache2/mods-available/passenger.conf

内容:

RailsSpawnServer /usr/lib/ruby/gems/1.8/gems/passenger-1.0.1/bin/passenger-spawn-server
RailsRuby /usr/bin/ruby1.8

passenger.confにはその他設定部分を記述します。

モジュールの有効化

mods-enabled以下にシンボリックリンクを作成します。

# ln -s /etc/apache2/mods-available/passenger.load /etc/apache2/mods-enabled
# ln -s /etc/apache2/mods-available/passenger.conf /etc/apache2/mods-enabled

httpd.confに追記

Readmine公式の手順*1では以下のような感じでVirtualHostに直に割り当ててます。

<VirtualHost *:80>
ServerName redmine.example.jp
DocumentRoot /var/lib/rails/redmine/public


しかし、これだと複数のRailsアプリで共存する場合に面倒になるので、RailsBaseURIを設定します。
以下のように追記します。

RailsBaseURI /redmine

Railsアプリを増やす場合には「RailsBaseURI hogehoge」という具合に行を追加しておけば良いです。


設定ファイルへの追記も完了したので、ファイルの配置を行います。
DocumentRoot以下にファイル一式を配置するよりはデプロイ場所へのシンボリックリンクを配置した方が使い勝手がいいです。

DocumentRoot以下にRAILS_ROOT/publicへのシンボリックリンクを配置する

以下はDocumentRootが/var/www、RAILS_ROOTが/home/hoge/rails/my_appになっている場合です。

# ln -s /home/hoge/rails/my_app/public /var/www/redmine

注意する点は以下の2点です。

Apacheの再起動と確認

ここまで設定すれば再起動でひとまず使えるはずです。
(rake db:migrateは忘れてないですよね?)

# /etc/init.d/apache2 restart

チューニングパラメータなど

いくつかチューニングパラメータがあります。
私はhttpd.confに記述してます。

RailsMaxPoolSize 4         #Apacheサーバ上に生成されるRailsのインスタンス数
RailsPoolIdleTime 240    #設定した時間(秒)以上インスタンスへのアクセスがなかった場合終了する


RailsMaxPoolSizeはメモリ量に応じて設定。
(メモリ[MB] / 64 - 2 程度のよう)
RailsPoolIdleTimeはユーザの平均滞在時間の2倍程度を設定。

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)にしただけですね。
一応、これでコンパイルは無事通りました。

Macのsayコマンドはおもしろい

Macには独自コマンドとしてsayコマンドというのがあります。
ターミナル (macOS) - Wikipedia


本来はユニバーサルアクセスのためのものですが、ターミナルに一行入力するだけでしゃべってくれるので意外とおもしろいです。
ちなみに英語のみ対応してますので、日本語をしゃべらせるにはコツがいります。


たとえば・・・。

ゆっくりしていってね

$ say you cooly shit tei it net.

しねばいいのに…

$ say she never e no knee.

そんな装備でダイジョブか?

$ say sonner so be de die job ka.

大丈夫だ。問題ない。

$ say die job daa. mon die nie.

そげぶ

$ say e zet. temay gat o moy dolly nit deckky ru ttenara. mazzle so no huzza ket a gen so o butch co-work sue.


などなど。
工夫次第でおもしろいことができそうです。
プレゼンとかでやると受けそうですね。


ちなみに-vオプションを指定すると声を変えることができます。
お試しあれ。(say autumn she array.)

今さらながらRedmineを使ってみんとす

ブログ書くのはかなり久しぶりですね。


さて、仕事とかでプロジェクト管理をすることもあるのですが、Excelでタスクや時間の管理をするのは一苦労です。
Microsoft Projectなどもありますが、ファイルベースで管理するのは複数人での情報共有が面倒なこともあり、できればWebベースでやりたいと考えています。

インストール

基本的には
Redmineのインストール - Redmineガイド
を見ながら作業すればよしです。

Railsとrack

1.0系を使うにはRailsの2.3.5、rackの1.0.1が必要です。(2011年1月現在)
gemでバージョンを指定してインストールします。
今回はrvm上のruby1.8.7を使います。

$ rvm 1.8.7
$ gem install rails --version '=2.3.5'
$ gem install rack --version '=1.0.1'
データベース

データベースはMySQLPostgreSQLSQLiteに対応しているようです。
今回はお試しなので導入の楽なSQLiteを使います。
MacにはSQLite3が最初から入っているので、インストールは省略。
SQLiteにはユーザという概念がないため、redmine用のデータベース、ユーザを作る必要はありません。

redmine

redmineのリリース版をチェックアウトします。

$ svn checkout http://redmine.rubyforge.org/svn/branches/1.0-stable redmine
$ cd redmine
$ ls
README.rdoc app         db          extra       lib         public      test        vendor
Rakefile    config      doc         files       log         script      tmp
database.yml

config/database.example.ymlを編集し、ファイル名をconfig/database.ymlで保存します。
以下はsqlite用。

production:
  adapter: sqlite3
  database: db/production.db
  timeout: 5000

development:
  adapter: sqlite3
  database: db/development.db
  timeout: 5000


sqlite3-rubyパッケージをインストールしていない場合は以下を実行。

$ gem install sqlite3-ruby
その他いろいろ
$ rake config/initializers/session_store.rb #セッションストア秘密鍵の生成
(in /Users/hakuro/ruby_src/redmine)
Missing the i18n 0.4.2 gem. Please `gem install -v=0.4.2 i18n`

#i18nライブラリの0.4.2がないと言われたのでgemでインストールし、再挑戦
$ gem install -v=0.4.2 i18n
$ rake config/initializers/session_store.rb

$ rake db:migrate RAILS_ENV="production" #データベース上にテーブルを作成
$ rake load_default_data RAILS_ENV="production" #デフォルト設定をロード 

redmineを実行するユーザが異なる場合は、files, log, tmpディレクトリに対して書き込み権限付与が必要ですが、今回は必要ないので省略。

起動
$ script/server webrick -e production #Webサーバをwebrickで起動

例によってブラウザでhttp://localhost:3000/にアクセスします。
管理画面が表示されたら成功です。

2010年12月20日のツイート