sqlite3用の設定

今回はSQlite3をつかうアプリなので、以下の記述を config/deploy.rb に追加します。

# config/database.ymlはsvnにコミットしません。
# ですので、サーバー側のshared以下にdatabase.yamlを保持するディレクトリを作成し、
# デプロイ時に config/database.yml はそのdatabase.ymlへのsymlinkとして作成します。
#
# また、本プロジェクトではDBにSQLite3を使います。
# production.sqlite3は shared以下にないといけないので、
# cap deploy:setupで自動的に作られるようにsetup後に呼び出す
# shared/dbを作るタスクを作成し、afterで登録します。
namespace :db do
  desc "setup directories for database"
  task :setup_shared_db_dirs do
    run "mkdir -p #{shared_path}/config #{shared_path}/db"
  end

  desc "Make symlink for shared/config/database.yml" 
  task :symlink do
    run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml" 
  end
end
after "deploy:setup", "db:setup_shared_db_dirs"
after "deploy:update_code", "db:symlink"

んで、ローカルでcap deploy:setupを実行

$ cap deploy:setup
  * executing `deploy:setup'
  * executing "mkdir -p /home/bar/capistrano/bar /home/bar/capistrano/bar/releases /home/bar/capistrano/bar/shared /home/bar/capistrano/bar/shared/system /home/bar/capistrano/bar/shared/log /home/bar/capistrano/bar/shared/pids &&  chmod g+w /home/bar/capistrano/bar /home/bar/capistrano/bar/releases /home/bar/capistrano/bar/shared /home/bar/capistrano/bar/shared/system /home/bar/capistrano/bar/shared/log /home/bar/capistrano/bar/shared/pids"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
    triggering after callbacks for `deploy:setup'
  * executing `db:setup_shared_db_dirs'
  * executing "mkdir -p /home/bar/capistrano/bar/shared/config /home/bar/capistrano/bar/shared/db"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished

こんな感じになると思います。
ちゃんとディレクトリが作られているのか確認してみましょう。
sshで普通に繋げてもいいのですが、cap shellというのがあるのでちょっとしたコマンドを実行するときは便利です。

$ cap shell
  * executing `shell'
====================================================================
Welcome to the interactive Capistrano shell! This is an experimental
feature, and is liable to change in future releases. Type 'help' for
a summary of how to use the shell.
--------------------------------------------------------------------
cap> pwd
[establishing connection(s) to ホスト名]
 ** [out :: ホスト名] /home/bar
cap> find ~/capistrano
 ** [out :: ホスト名] /home/bar/capistrano
 ** [out :: ホスト名] /home/bar/capistrano/bar
 ** [out :: ホスト名] /home/bar/capistrano/bar/releases
 ** [out :: ホスト名] /home/bar/capistrano/bar/shared
 ** [out :: ホスト名] /home/bar/capistrano/bar/shared/system
 ** [out :: ホスト名] /home/bar/capistrano/bar/shared/log
 ** [out :: ホスト名] /home/bar/capistrano/bar/shared/pids
 ** [out :: ホスト名] /home/bar/capistrano/bar/shared/config
 ** [out :: ホスト名] /home/bar/capistrano/bar/shared/db
cap> quit
exiting

ちゃんとセットアップできたようなので、shared/config/database.ymlを作成しましょう。
こんどはちゃんとSSHでログインして、/home/bar/capistrano/bar/shared/config/database.ymlを以下のように作成します。

common: &common
  adapter: sqlite3
  pool: 5
  timeout: 5000

development:
  database: /home/bar/capistrano/bar/shared/db/development.sqlite3
  <<: *common

test:
  database: /home/bar/capistrano/bar/shared/db/test.sqlite3
  <<: *common

production:
  database: /home/bar/capistrano/bar/shared/db/production.sqlite3
  <<: *common

で、これでいざデプロイしてみましょう。

リモートでsvn infoする設定

$ cap deploy:update
  * executing `deploy:update'
 ** transaction: start
  * executing `deploy:update_code'
    updating the cached checkout on all servers
    executing locally: "svn info file:///var/svn/bar-repo/trunk  -rHEAD"
svn: Unable to open an ra_local session to URL
svn: Unable to open repository 'file:///var/svn/bar-repo/trunk'
*** [deploy:update_code] rolling back
  * executing "rm -rf /home/bar/capistrano/bar/releases/20090411164633; true"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
/opt/local/lib/ruby/gems/1.8/gems/capistrano-2.5.3/lib/capistrano/recipes/deploy/scm/subversion.rb:58:in `query_revision': tried to run `svn info file:///var/svn/bar-repo/trunk  -rHEAD' and got unexpected result "" (RuntimeError)
	from /opt/local/lib/ruby/gems/1.8/gems/capistrano-2.5.3/lib/capistrano/recipes/deploy/scm/base.rb:35:in `send'
	from /opt/local/lib/ruby/gems/1.8/gems/capistrano-2.5.3/lib/capistrano/recipes/deploy/scm/base.rb:35:in `method_missing'
(以下略)

失敗してしまいました。これは、リビジョンを取得するのに実行するsvn infoをローカルのPCで実行したためです。通常はそれでいいと思うのですが、今回はリポジトリも同じサーバーなので、この辺の処理を書き換えてしまいましょう。

リビジョンを取得する処理は、gems/capistrano-2.5.3/lib/capistrano/recipes/deploy.rb の 以下の部分で記述されています。

_cset(:real_revision)     { source.local.query_revision(revision) { |cmd| with_env("LC_ALL", "C") { run_locally(cmd) } } }

これをローカルじゃなくてリモートで実行したい訳です。なので、安直に

set(:real_revision)     { source.query_revision(revision) { |cmd| with_env("LC_ALL", "C") { run(cmd) } } }

とするとエラーになります。これは、run_locallyメソッドが返していたsvn infoの結果をrunメソッドは返さないからです。なので、ちょっとややこしいですが以下のようにします。

# バージョンを取得するsvn infoコマンドは通常run_locallyで実行されますが、
# 今回はログインしたサーバーで取得したいので、デフォルトの設定を変更します。
set(:real_revision) do
  source.query_revision(revision) do |cmd| 
    result = nil
    with_env("LC_ALL", "C") { run(cmd){|conn, out, res| result = res} } 
    result
  end
end

これで正しくリビジョンが取得できるようになりました。再度 svn deploy:update してみましょう。

$ cap deploy:update
  * executing `deploy:update'
 ** transaction: start
  * executing `deploy:update_code'
    updating the cached checkout on all servers
  * executing "svn info file:///var/svn/bar-repo/trunk  -rHEAD"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
  * executing "if [ -d /home/bar/capistrano/bar/shared/cached-copy ]; then svn update -q  -r17 /home/bar/capistrano/bar/shared/cached-copy; else svn checkout -q  -r17 file:///var/svn/bar-repo/trunk /home/bar/capistrano/bar/shared/cached-copy; fi"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
    copying the cached version to /home/bar/capistrano/bar/releases/20090411171455
  * executing "cp -RPp /home/bar/capistrano/bar/shared/cached-copy /home/bar/capistrano/bar/releases/20090411171455 && (echo 17 > /home/bar/capistrano/bar/releases/20090411171455/REVISION)"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
  * executing `deploy:finalize_update'
  * executing "chmod -R g+w /home/bar/capistrano/bar/releases/20090411171455"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
  * executing "rm -rf /home/bar/capistrano/bar/releases/20090411171455/log /home/bar/capistrano/bar/releases/20090411171455/public/system /home/bar/capistrano/bar/releases/20090411171455/tmp/pids &&\\\n      mkdir -p /home/bar/capistrano/bar/releases/20090411171455/public &&\\\n      mkdir -p /home/bar/capistrano/bar/releases/20090411171455/tmp &&\\\n      ln -s /home/bar/capistrano/bar/shared/log /home/bar/capistrano/bar/releases/20090411171455/log &&\\\n      ln -s /home/bar/capistrano/bar/shared/system /home/bar/capistrano/bar/releases/20090411171455/public/system &&\\\n      ln -s /home/bar/capistrano/bar/shared/pids /home/bar/capistrano/bar/releases/20090411171455/tmp/pids"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
  * executing "find /home/bar/capistrano/bar/releases/20090411171455/public/images /home/bar/capistrano/bar/releases/20090411171455/public/stylesheets /home/bar/capistrano/bar/releases/20090411171455/public/javascripts -exec touch -t 200904111714.56 {} ';'; true"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
    triggering after callbacks for `deploy:update_code'
  * executing `db:symlink'
  * executing "ln -nfs /home/bar/capistrano/bar/shared/config/database.yml /home/bar/capistrano/bar/releases/20090411171455/config/database.yml"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
  * executing `deploy:symlink'
  * executing "rm -f /home/bar/capistrano/bar/current && ln -s /home/bar/capistrano/bar/releases/20090411171455 /home/bar/capistrano/bar/current"
    servers: ["ホスト名"]
    [ホスト名] executing command
    command finished
 ** transaction: commit

おおーできたっぽい。さっそく確認ー。

$ cap shell
  * executing `shell'
====================================================================
Welcome to the interactive Capistrano shell! This is an experimental
feature, and is liable to change in future releases. Type 'help' for
a summary of how to use the shell.
--------------------------------------------------------------------
cap> ls -la ~/capistrano/bar/releases/
[establishing connection(s) to ホスト名]
 ** [out :: ホスト名] total 12
 ** [out :: ホスト名] drwxrwxr-x  3 bar bar 4096 Apr 12 02:18 .
 ** [out :: ホスト名] drwxrwxr-x  4 bar bar 4096 Apr 12 02:18 ..
 ** [out :: ホスト名] drwxrwxr-x 16 bar bar 4096 Apr 12 02:18 20090411171819

うひょー!ばっちりー!


ではSSHでログインして、確認してみましょう。

$ cd ~/capistrano/bar/current
$ ruby script/console
>> ActiveRecord::Base.connection.tables
MissingSourceFile: no such file to load -- sqlite3
	from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
(以下略)

あ、sqlite3-rubyを入れてなかった。

sqlite3-rubyのインストール

# gem install sqlite3-ruby
Building native extensions.  This could take a while...
ERROR:  Error installing sqlite3-ruby:
	ERROR: Failed to build gem native extension.

/usr/bin/ruby extconf.rb install sqlite3-ruby
checking for fdatasync() in -lrt... yes
checking for sqlite3.h... yes
checking for sqlite3_open() in -lsqlite3... no

make
make: *** No rule to make target `ruby.h', needed by `sqlite3_api_wrap.o'.  Stop.


Gem files will remain installed in /usr/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.4 for inspection.
Results logged to /usr/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.4/ext/sqlite3_api/gem_make.out
#

これはよくあるパターン。-develが入ってないっぽい。
調べてみると、sqlite-develが入っていないっぽい。

# yum list sqlite3
(中略)
=================================================================== Matched: sqlite3 ====================================================================
sqlite-devel.i386 : Development tools for the sqlite3 embeddable SQL database engine.
sqlite-devel.x86_64 : Development tools for the sqlite3 embeddable SQL database engine.
# 

早速インストール。

# yum install sqlite-devel

で、sqlite3-rubyもインストール

# gem install sqlite3-ruby

ばっちり!
もう一回試してみる。

$ ruby script/console
>> ActiveRecord::Base.connection.tables
=> []
>> exit

おっけー!DBに接続できた!

では、こんどはちゃんとcapistranoマイグレーションしてみましょう。

$ cap deploy:migrate 

成功すれば、マイグレーションの結果が出力されるはずです。

おっけー!では、サーバーを起動してみましょう

$ cap deploy:start
  * executing `deploy:start'
  * executing `mongrel:cluster:start'
  * executing "mongrel_rails cluster::start -C /etc/mongrel_cluster/bar.yml"
    servers: ["ホスト名"]
    [ホスト名] executing command
*** [err :: ホスト名] !!! Configuration file does not exist. Run mongrel_rails cluster::configure.
*** [err :: ホスト名] 
*** [err :: ホスト名] cluster::start reported an error. Use mongrel_rails cluster::start -h to get help.
*** [err :: ホスト名] 
    command finished
failed: "sh -c \"mongrel_rails cluster::start -C /etc/mongrel_cluster/bar.yml\"" on ホスト名

ああ、mongrel_clusterの設定をしてなかったっすね。

mongrel_clusterの設定

mongrel_clusterの設定をやっちゃいましょう。
ローカルのRAILS_ROOTで

$ mongrel_rails cluster::configure -e production -p 8000 -N 3 -c /home/bar/capistrano/bar/current --user bar --group bar

を実行すると、config/mongel_cluster.yml ができるので、コミットしてsvnに反映させます。で、サーバーに反映させます。

$ cap deploy:update

サーバーにSSHでログインして、以下の処理を行います。

$ sudo mkdir /etc/mongrel_cluster
$ sudo ln -s /home/bar/capistrano/bar/current/config/mongrel_cluster.yml /etc/mongrel_cluster/bar.yml

これは後々自動起動用に使うから/etcの下に置いています。詳しくは http://mongrel.rubyforge.org/wiki/MongrelCluster を参照してください。

で改めて、起動

$ cap deploy:start
  * executing `deploy:start'
  * executing `mongrel:cluster:start'
  * executing "mongrel_rails cluster::start -C /etc/mongrel_cluster/bar.yml"
    servers: ["bar.com"]
    [bar.com] executing command
 ** [out :: bar.com] starting port 8000
 ** [out :: bar.com] starting port 8001
 ** [out :: bar.com] starting port 8002
    command finished

まだapacheの設定をしていないので、SSHでログインして、

$ wget http://localhost:8000

でindex.htmlができていれば成功です。

$ ps aux | grep ruby

あと、プロセスが起動していることを確認してください。

明日はapacheの設定をやります。

覚え書き

# rake gems:install 

でconfig/environment.rbに記述してあるgemが入るはずなんですが、
同時もうまく行きませんでした。# gem sources -a http://gems.github.com もしてあるのに。
仕方ないので、手動で以下のgemをインストールしました。

# gem install mislav-will_paginate kakutani-yaml_waml rspec rspec-rails mongrel mongrel_cluster sqlite3-ruby