Ruby 2.0 + Sinatra + Thin を Windows サービス化してみた
簡単な Web アプリを Ruby + Sinatra で作って、それを Windows サービス化しようとしたらすごくハマったのでメモしておく。 最終的には Thin を使って Winsw で Windows サービス化した。
リポジトリは https://github.com/toruuetani/SinatraThinService
※ Ruby は 2.0 から使い始めたのでほとんど知らない。おかしいところがあれば指摘してください。
前提
- Windows 7 SP1 Professional
- Ruby 2.0.0-p195 (RubyInstaller for Windows)
- Bundler 1.1.5
- Sinatra 1.4.2
- Thin 1.5.1
Ruby 製 HTTP サーバー
とりあえず検索してみたところ有名なのはこれくらいらしい。
WEBrick は開発向けなので除外するととして、 Passenger と Unicorn は Windows で動かないので問題外。 そうなると Mongrel と Thin しか候補がないんだけども、 Mongrel はすでに開発が止まっているらしい。 実際 Ruby 1.9 には正式に対応しておらず、開発版でなんとか動く状況のようだ。 Ruby 2.0 ではほぼ情報がなく、開発版でも動作しなかったので Thin しか望みがない。
ただし、 Mongrel では mongrel_service というそのものずばりの gem があったんだけども Thin には Windows サービス化する方法がない。
winsw: Windows Service Wrapper
そこで kohsuke/winsw という実行モジュールを Windows サービス化する ユーティリティを使うことにした。 Jenkins でも使われているものなので、信頼性も十分だろう。
ただ困ったことに Bundler のように子プロセスを起動する場合には対応しておらず、サービスを停止しても子プロセスが 停止してくれない。モダンな Ruby 環境であるなら Bundler ははずせないだろう、と思ったのがいろいろハマった原因の一つ。
起動自体は問題ないが、停止できないのは気持ち悪いので少し変更して使うことにした。
Sinatra の準備
ここからは実際に動かす方法を記述していく。
Ruby は C:\Ruby200
にインストールされているものとして Bundler をインストールしておくこと。
gem install bundler
Bundler をインストールしたら作業ディレクトリで以下のコマンドを実行する。
※ thin の依存ライブラリ eventmachine のコンパイルに必要なので、 DevKit と gcc をインストールしておくこと。
bundle init #Modify Gemfile bundle install --path vendor/bundle
# A sample Gemfile source "https://rubygems.org" gem "sinatra" group :development do gem "sinatra-contrib" gem "better_errors" gem "binding_of_caller" end gem "thin"
最低限 Sinatra が動くコードを用意する。
# -*- encoding: utf-8 -*- # app.rb require "rubygems" require "sinatra" get "/" do "Hello" end
bundle exec ruby app.rb
で http://localhost:4567
が動くことを確認する。
または config.ru
を用意して bundle exec rackup
で http://localhost:9292
が動くことを確認する。
# -*- encoding: utf-8 -*- # config.ru require "./app.rb" run Sinatra::Application
winsw の準備
現時点での最新(1.13)だと子プロセスを停止できないので、 Bundler 経由だと winsw を停止しても Thin が停止できない。
winsw.exe -> ruby(Bundler) -> ruby(Thin) となるので winsw.exe を停止しても ruby(Bundler) しか停止されない。
なのでパッチを当てたものを使う(上記リポジトリに含まれる SinatraThinService.exe
)。
winsw.exe
の設定は winsw.xml
で行う。名前は任意のものに変更可能。ポイントは次の通り。
- Bundler で使う
Gemfile
を環境変数BUNDLE_GEMFILE
で指定する。 workingdirectory
を指定する。
<service> <id>SinatraThinService</id> <name>SinatraThinService</name> <description>Sinatra with Thin Service</description> <env name="PATH" value="C:\Ruby200\bin;%PATH%;"/> <env name="BUNDLE_GEMFILE" value="C:\Documents\Work\SinatraThinService\Gemfile"/> <executable>ruby</executable> <arguments>C:\Ruby200\bin\bundle exec ruby .\vendor\bundle\ruby\2.0.0\bin\thin -R .\config.ru start</arguments> <workingdirectory>C:\Documents\Work\SinatraThinService</workingdirectory> <logmode>rotate</logmode> </service>
サービスの使い方
管理者権限でコマンドプロンプトを起動し、以下のコマンドを実行する。これで http://localhost:3000
でアクセスできるか確認する。
SinatraThinService install SinatraThinService start
停止するときは
SinatraThinService stop
アンインストールは次の通り。
SinatraThinService uninstall