| @技術/プログラミング

Unicorn の設定をミスって(たと思ってけど実はそうじゃなかった)ポータルシットが12月の半ば頃から死んだままになってた。きっかけは Capistrano の導入で、仕事で Capistrano 使っていて大変便利なので、これをポータルシットでも使おうとした。

Unicorn で便利なのが、 kill -USR2 `cat tmp/pids/unicorn.pid` とかやることで、ダウンタイム無しに Rails アプリケーションを再起動できるとこだ。これを Sinatra 製の Lokka でも実現したかった。Capistrano と併せて運用することで、サーバーに SSH で接続せずとも

$ bundle exec cap deploy:restart

とかで Lokka を再起動できるようになる。

これまで Lokka の database.yml に DB への接続情報をべた書きしていたのをやめ、起動時にはシェルで以下のコマンドを実行するようにした。

$ env DATABASE_URL=path/to/db bundle exec unicorn -c config/unicorn.rb -D -E production

Capistrano の deploy.rb に書くと以下のようになる。

namespace :deploy do
  task :start do
    run "cd #{current_path}; env DATABASE_URL=#{db_path} bundle exec unicorn -c config/unicorn.rb -D -E production"
  end
end

| @技術/プログラミング

RVM、便利に使わせてもらっていたけど、Rubyの新しいのがリリースされるたびにいろいろアレだったので rbenv を使ってみることにした。移行、しんどいかなと思ってたけど非常に簡単で大変よかった。

RVMのキモさ

RVMの悪いところはググればいろいろ出てくるけど、OSの cd やRubyの gem コマンドをシェルスクリプトで置き換えるとか、行儀が悪いところが問題らしい。個人的に気にくわなかったのがRVMがどんどんでかくなっていって、Rubyのビルドに必要なパッケージまで管理できるようになったところとか(.rvm以下に新しくシステムができるみたいな感じがキモかった)、パッケージインストール用のコマンドがhelpドキュメントでは rvm package install なのに rvm pkg install にいつの間にか変わっていて訳がわからないところとか、よくわからないシェルスクリプトがログイン時に実行されるところとか、 rvmsudo っていうコマンドのキモさとかいろいろ。

rbenv

rbenvはRubyのバージョンを切り替えるためのツールなのでインストールはやってくれないけど、ruby-buildというツールを別に入れることで、 rbenv install 1.9.2-p290 とかでRubyのインストールもこなしてくれるようになる。

あまりRVMを使いこなしてたとはいえなかった自分にとってはrbenvくらいでちょうどいいような感じがする。gemsetとか使わんし。そんくらいだったBundler使うし。

インストールは以下のページが参考になります。

なおrbenvはRubyインストール時のconfigureオプションの指定方法が特殊です。直接は指定できないようなので以下のようにします。(homebrewでインストールしたreadlineとiconvのパスを指定する例)

$CONFIGURE_OPTS="--with-readline-dir=/usr/local --with-iconv-dir=/usr/local" rbenv install 1.9.2-p290

デフォルトのオプションなしのRubyだとearthquake.gemが動かなかったりjekyllが使えなかったりするので僕は↑のオプションを追加しました。よろしかったらお試し下さい。

| @技術/プログラミング

LokkaをCMSに採用している ポータルシット はHerokuで動かしてたんだけど、Lokkaをカスタマイズして使っているためか、デプロイしてもApplication Errorばかり出るようになってしまった。ローカルのMacではうまくいくのに。一週間くらい直そうと努力してみたけど直りそうにないのでHerokuでの運用を諦めてさくらVPS上のUbuntuで運用することにした。すこぶる快適。

Herokuは確かに便利なんだけど、Herokuの中でどういう風にアプリケーションが動いているのかを把握しづらい。ファイルシステムに直接アクセスできないので、ログを見るにも heroku logs とかやんないといけない。

その点、自分で環境をいじれるサーバーだったらウェブアプリケーションのログはおろかシステムログまで見られるし、無理にHerokuで運用してHerokuで運用するために時間を割くのは馬鹿らしいような気がする。

| @技術/プログラミング

Ruby 1.9.2-p290 がリリースされたので入れてみた。RVMで。

$ rvm install 1.9.2 --with-readline-dir=/usr/local #homebrewで入れたreadlineのパスを指定
$ rvm migrate ruby-1.9.2-p180 ruby-1.9.2-p290

migrate を実行したところ、警告が出ながらも次のような感じでマイグレーションは完了した。

$ rvm migrate ruby-1.9.2-p180 ruby-1.9.2-p290
Are you sure you wish to MOVE gems from ruby-1.9.2-p180 to ruby-1.9.2-p290?
This will overwrite existing gems in ruby-1.9.2-p290 and remove them from ruby-1.9.2-p180 (Y/n): Y
Moving gemsets...
Moving ruby-1.9.2-p180 to ruby-1.9.2-p290
Making gemset ruby-1.9.2-p290 pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /usr/local/rvm/log//gemset.pristine.log
Moving ruby-1.9.2-p180@global to ruby-1.9.2-p290@global
Making gemset ruby-1.9.2-p290@global pristine.
ERROR: Error running 'rvm gemset pristine' under ,
please read /usr/local/rvm/log//gemset.pristine.log
Do you wish to move over aliases? (Y/n): Y
Do you wish to move over wrappers? (Y/n): Y
Do you also wish to completely remove ruby-1.9.2-p180 (inc. archive)? (Y/n): Y
Successfully migrated ruby-1.9.2-p180 to ruby-1.9.2-p290

一見、問題なく移行できたように思えるのだけど、この後rakeなどexecutableなgemをコマンドラインから実行すると以下のようなエラーが出る。

zsh: /usr/local/rvm/gems/ruby-1.9.2-p290/bin/rake: bad interpreter: /usr/local/rvm/rubies/ruby-1.9.2-p180/bin/ruby: no such file or directory
rake aborted!
No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)
/usr/local/rvm/gems/ruby-1.9.2-p290/gems/rake-0.8.7/lib/rake.rb:2377:in `raw_load_rakefile'
(See full trace by running task with --trace)

shebangに書いてあるrubyのパスがmigrate時に削除した ruby-1.9.2-p180 なのが問題なわけだ。

正しい対処方法かどうかは自信がないが、Rubyでサクサクッとshebangを書き換えるやつを書いた。以下みたいなやつ。

こいつを実行してやるとshebangが正しく書き換わったexecutableなgemができる。万が一のためにbackupファイルを作るのでこれをzshで rm *_backup とかしてやるといいと思います。

と思ったけど、結局↑のRubyの入れ方はまずいみたいで、jekyllとかCライブラリに依存する系のgemが動かなくなってしまったので rvm implode してRVMをまるっと入れ替えた(20回くらいRubyをインストールしなおした)。次の記事にでも書きます…。

| @技術/プログラミング

暇だったので自動で特定のユーザーを延々favし続けるスクリプトを書いた。

ヒトデ君が書いた hitode909/user-stream-receiver - GitHubRuby+User Stream APIで無言リプライに高速返信するbotを作りました - ps aux | grep aquarla を参考にさせてもらった。というかほとんどまるパクリ。またOAuthのところはtily氏の tily/ruby-oauth-cli-twitter - GitHub に全面的に依存している。

User Stremを受診してるのでcronとかの設定なしでネットストーキングしたい相手のことを延々追跡できる。しかも発言があった瞬間に即favする。大変気持ち悪いですね。

しかしUser Streamはときどき調子が悪く、発言を拾い落とすこともある。そんなときは以下のコードを使う。

これでUser Stream経由で取りこぼした発言もfavできる。それぞれ使い方はこんな感じ。

$ ruby favoritter.rb ストーキングしたい相手のユーザー名
$ ruby favstream.rb ストーキングしたい相手のユーザー名

| @技術/プログラミング

ポータルシットをLokkaに置き換えたくていろいろやってる。ポータルシットの過去記事をYAMLでエクスポートし、それをLokkaのDBに取り込む作業をやってる。TDD BootCampに参加したので、テストファーストしながらの作業。RSpecでテストコードを書き、ログが正しくインポートできることを確認する。テスト終了時 after(:all) フックで、取り込んだログを削除してる。コードはこんな感じ。ちなみにLokkaはDataMapperをORMに採用してるので以下はDataMapperでの話。

after(:all) do
  Category.all.destroy
  Entry.all.destroy
end

しかしこれでは AUTO INCREMENT の値がリセットされず、テストを繰り返す度に AUTO INCREMENT の値が増えていってうざかった。

DataMapperの機能で AUTO INCREMENT 値をリセットするのってないのかなと5秒くらい探してみたけど見つからなかったので、SQLを直接実行する方法を採用した。

ちなみにRDBMSに採用してるのはSQLite3。SQLiteでは UPDTE sqlite_sequence SET seq=0 WHERE name='テーブル名'; みたいなコードで AUTO INCREMENT 値を任意の値に設定できるみたい。

最終的な after(:all) フックはこんな感じ。

  after(:all) do
    Category.all.destroy
    Entry.all.destroy
    Entry.repository.adapter.execute('update sqlite_sequence set seq=0 where name="entries";')
  end

テスト実行後にはすべてのデータがデータベースから削除されて、AUTO INCREMENT の値もリセットされる。人畜無害なテストコード万歳。

| @技術/プログラミング

確認ダイアログを出しながらディレクトリやファイルを削除するスクリプトを書いた。大したコード書いてないし逆引きRubyに載ってたコードをまるパクリしてるところもあるけど便利だと思う。

そのディレクトリにあるファイル/ディレクトリ一覧を取得した後、「このファイル/ディレクトリは作られてから何日経っています。削除しますか? (y/n)」というダイアログ(英語)を表示する。y が入力されると削除を行う。地味に使える。

RubyのFileUtilsはすごく便利だと思う。シェルスクリプトでしこしこ書くのがアホらしくなる。RubyがPerlなみにあらゆるuni*x系のサーバーに入るようになったらさぞかし便利だろうと思う。