0

Ubuntu12.04にrbenvインストールして、crontabやdaemontoolsも設定した

さくらVPSのUbuntu12.04のrvmをrbenvに切り替えた

関連

mac版
橋本商会 » rvmからrbenvに乗り換えた
橋本商会 » crontabでrbenvのrubyを使う

準備


先にrubyをbuildするのに必要なaptを入れる(先にrvmを使っていたのでこれは必要なかったが)
sudo apt-get install build-essential libreadline-dev libssl-dev


rvmを消す
rvm seppuku
sudo rm -rf ~/.rvm


ホームディレクトリにrbenvを入れる


rbenvはaptにもあるけどruby-buildが無いので両方githubからcloneした。
git clone git://github.com/sstephenson/rbenv.git ~/.rbenv
mkdir ~/.rbenv/plugins
git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build


rbenvへのパスを通す。 ~/.zshrc に書けばいい・・
export PATH=$PATH:$HOME/.rbenv/bin
eval "$(rbenv init -)"
と思いきや、screenを起動したりzsh上でzshを起動するとrbenvのパスより上に /usr/local/bin 等が来て、system rubyが使われてしまう現象が起きた。

rbenvのissueやドキュメントを確認したり調べてみると
Unix shell initialization · sstephenson/rbenv Wiki
インストールしたてのUbuntu12.04では /etc/zsh/zshrc や /etc/zlogin がPATHをいじってた。
一番最後にロードされるらしい ~/.zlogin にrbenvの設定を書いたらscreen上でもrbenvが正しくロードされた。


ruby 2.0.0インストール
rbenv -v
rbenv install --list | grep 2.0
rbenv install 2.0.0-p0


デフォルトでruby2.0使うようにする。
rbenv global 2.0.0-p0
rbenv rehash
ruby -v
2.0になってればok


gemをアップデートしたり、自動rehashするrbenv-rehashを入れたり
gem update --system
rbenv rehash
gem install rbenv-rehash bundler
rbenv rehash


jrubyもインストールする
rbenv install jruby-1.7.3


jrubyのソースコード置いてある場所でだけ、ruby2.0からjruby1.7に切り替えるようにする
cd ~/src/jruby
rbenv local jruby-1.7.3
rbenv rehash
ruby -v
jrubyになっていればおk


rubygemとbundlerをアップデートしたり、自動的にrehashするようにする。
gem update --system
rbenv rehash
gem install rbenv-rehash bundler
rbenv rehash
このディレクトリの下でだけjrubyが使われるようになる。


crontabでrbenvのrubyを使う


crontabの上の方で、PATHの先頭に ~/.rbenv/shims を入れる。
あとはアプリのディレクトリまでcdしてからrubyを使うようにすれば、ちゃんとGemfileも.ruby-vesionも読んで実行してくれる。
HOME=/home/shokai
PATH=/home/shokai/.rbenv/shims:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/home/shokai/bin

*/15 * * * * cd $HOME/src/ruby/twitter-change-profile && ruby change-profile.rb
*/20 * * * * cd $HOME/src/jruby/glitchicon && ruby bin/create_icon.rb $HOME/shokai.png /var/tmp/glitch_icon.png && ruby bin/upload.rb /var/tmp/glitch_icon.png
jruby使うアプリもちゃんとrbenv切り替えて実行してくれてた。


事前にcrontab上でrbenvが正しく動くかを確かめたほうがいい。
* * * * * echo $PATH > $HOME/cron-path.txt
* * * * * ruby -v > $HOME/cron-ruby-version.txt
* * * * * cd $HOME/src/jruby && ruby -v > $HOME/cron-jruby-version.txt
こういうの登録したらホームディレクトリに環境変数とか書き出す。
なんだか知らんが、Macではできるのに、PATHへの代入の右項に$HOMEとか書いても変数展開されない現象が起きてた。


daemontoolsでrbenvのrubyを使う


daemontoolsはlogが確認しやすいので楽。

http://dev.shokai.org:4000 の起動スクリプト。
cronと同じようにパスの先頭にshimsを追加すればいい。

/etc/service/rocketio-chat/run
#!/bin/sh
exec 2>&1
exec setuidgid sho bash -c '
HOME=/home/shokai
PATH=$HOME/.rbenv/shims:$PATH
cd $HOME/src/sinatra/rocketio-chat-sample
WS_PORT=18080 rackup config.ru -p 4000
'

0

githubの自分のリポジトリのissue一覧を見るツール

自分にアサインされたissueは通知が来るけど、
自分が持ってるリポジトリのissue一覧が無いのでgithub API使って簡単なCLIツール作った

全部表示すると精神衛生上よくないので60日以内に更新があったリポジトリだけ表示するようにした

shokai/github-cmd · GitHub


octokitっていうrubygemがなかなか使いやすかった。よくあるfaradayで取得してHashie::Mashで返してくれるタイプ。
pengwynn/octokit · GitHub

0

Sinatra RocketIO v0.2.0でchannel機能がついた

前:Sinatra RocketIOというプラグイン作った、これでWebSocketとCometが使える

クライアントのグループを作る機能を追加した。
例えばチャットルームを分ける時などに使ってください。

クライアント側が接続する時にチャンネル名を指定すると、サーバー側で管理されているチャンネルリストに追加される。

var io = new RocketIO({channel: "チャンネル名"}).connect();
io.on("hoge", function(data){
alert(data);
});


サーバー側からチャンネルを指定して送信する
Sinatra::RocketIO.push :hoge, "ホゲ", :channel => "チャンネル名"

サンプルも更新してあるのでどうぞ


こうすれば、 http://アプリ名/chat/チャットルーム名 でグループ分けできる。

sinatra側でURLからチャットルーム名を取り出してチャンネル名とし、
get '/chat/:channel' do
@channel = params[:channel]
haml :chat
end


viewテンプレートでjavascriptにチャンネル名を渡して
:javascript
var channel = "#{@channel}";


接続時にchannelを指定する。
var io = new RocketIO({channel: channel}).connect();

5

Ruby書くならBundler使え

Rubyでプログラム書くにあたって、bundlerを使わないプログラムは1年ぐらい経つと動かなくなってる事が多々あって、bundlerマジ重要なのと
ぐぐってもあまりbundlerの利点や説明がまとまってる記事がなかったので

研究室のwikiに書いた記事を転載しておく。



Bundlerとは


Bundler: The best way to manage a Ruby application's gems

プロジェクト内で使うRubygemsを管理するしくみ。
プロジェクトの一番上のディレクトリに「Gemfile」というテキストファイルを置き、その中にgemの名前(と必要あればバージョンも)書く。
% bundle install
というコマンドで、gemが一括インストールできる

プログラム内で
require 'bundler'
Bundler.require
と書くと、gemが一括requireできる


どんな時に便利なの?


使用するgemのバージョンを指定できる


開発環境とデプロイ環境で完全に同じバージョンのgemを使えると、無駄なバグが起こらない


gemがメジャーバージョンアップして仕様が変わってしまったので、古いのを使いたい事がある。
railsとかtwitter gemとか、バージョンアップも速いし各バージョンでAPIに互換性がない


あるプロジェクトではtwitter gem 5.x系を、別のプロジェクトでは4.x系を使いたい場合
bundlerなしで
require 'twitter'
するとどちらのプロジェクトでも、バージョンの大きい5.xを読み込んでしまう
そのマシンに存在する最もバージョンの大きいtwitter gemを読み込んでしまうのだ
つまり、新しくtwitter gemを使ったプロジェクトを始めるだけで、古いプロジェクトは何も手を触れていないのに壊れてしまう


作ったプログラムが1年後もちゃんと動くにはbundler必須だとお分かりいただけましたか


rubygems.org以外でホストされているgemをインストールできる

gitリポジトリを指定してインストールできるので、
部外秘なgemは学内に置いておきつつ、Herokuにインストールさせるとかも可能
特定のgit branchやtagを指定してインストールも可能
既存のgemをgithub上でforkして、ちょっとカスタムして使う事もできる
rubygems.orgが死亡してしまった時にも使える


プロジェクトのディレクトリにgemをインストールできる

% bundle install --path (ディレクトリ名)
gemそのものをちょっと修正して使う時や、gemのバグ探しなどに便利


使用方法伝授


準備
まずRubygemsを2.0.0以上にアップデートしておく。
% gem update --system
% gem -v


bundlerをインストール
% gem install bundler
最新版は1.3.4です


Gemfile というテキストファイルを作成し、使用するgemを列挙する
source 'https://rubygems.org'
gem 'sinatra'
gem 'mongoid', '>=2.4.0', '<3.0.0'
gem 'json', '~> 1.7'
gem 'tw', :git => 'git@github.com:shokai/tw.git'
意味 – sinatraはどのバージョンでもいい、mongoidは2.4以上3未満、jsonは1.7.x系の最新、twはgithubから開発版をインストール

このファイルはbundle initすれば雛形を生成してくれるので、書式忘れたらinit。


gemをインストール

% bundle install


Gemfile.lockが無い場合(はじめてbundle installした時)
Gemfile.lockというファイルが生成される
gemの名前とバージョンが列挙されている
これをgitにcommitしておくと吉
Gemfileではゆるめにバージョン指定して、詳細はGemfile.lockに任せた方がいい


gemのインストール元
ローカルにないgemはrubygemsから最新版が
ローカルにあるgemは、ローカルにある中で一番バージョン番号が大きいものがインストールされる


Gemfile.lockがある場合(2回目以降のbundle install時)
書いてあるバージョンのgemがインストールされる


gemのアップデート

% bundle update
rubygems.orgから最新版を取得し、Gemfile.lockを更新する



bundlerで指定したgemを使う

これやらないと、システムに入っている最新版gemを使ってしまいます


bundlerで指定したgemを使う(実行時に指定)
今まで
% ruby foo.rb
% rackup config.ru
等で実行していたのを、
% bundle exec ruby foo.rb
% bundle exec rackup config.ru
とする


bundlerで指定したgemを使う(プログラム内で指定)
require 'bundler/setup'
これを書けば使用バージョンがGemfile.lockに書かれている物に固定される(俺はこっち派)

個別にrequireしてもいいし、
Bundler.require
でgemを一括requireしてもいい。


Gemfileはカレントディレクトリにある物を参照するので、crontabで使う場合はプロジェクトの中にcdしてからrubyしないといけません。
7時30分に実行する例
30 7 * * * cd $HOME/src/ruby/myapp && bundle exec ruby start.rb > /dev/null 2>&1


gemのテンプレも作れる


% bundle gem 名前
でgemの雛形が作れる。
作ったgemは特に審査などなくrubygems.orgにホストしてもらえて、世界中に大公開されてみんなに使ってもらえるのでどんどん作るといいと思います



まとめ


そんな感じで、Rubygemsたちの更新は速いのでGemfileをちゃんと書かないとすぐにプログラムは動かなくなります。
Bundlerを使いましょう

2

crontabでrbenvのrubyを使う

関連 crontabでRVMのRubyを使う

crontabの頭で環境変数PATHに ~/.rbenv/shims を入れておけばおk


うちではこんなふうになっている

SHELL=/usr/local/bin/zsh
HOME=/Users/sho
PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/$HOME/bin:$PATH
PATH=$HOME/.rbenv/shims:$PATH

## この下にcrontabが書かれている


ちゃんと切り替えれているか確認

ruby -vでバージョンがでるので、
* * * * * ruby -v > $HOME/ruby_version
と書いておけばホームディレクトリにruby_versionというファイルが毎分書き出される
これがrbenvでglobal設定したrubyになっているか確認する。
ちゃんとPATHに $HOME/.rbenv/shims が追加できていれば2.0.0とか書き込まれる。



ディレクトリ毎の確認

rbenv local 1.9.2-p320
でそのディレクトリに .ruby-version というrbenvの設定ファイルができる
これがあると、そのディレクトリに入ったらrbenvが切り替わる。


また、rbenv-rehashというgemを入れておけば自動的にrehashしてくれる。
gem install rbenv-rehash


1.9.2にだけarduino_firmata gemを入れて、ディレクトリ毎にrbenv切り替えがcrontab上でも有効なのか試す
mkdir ~/tmp/1.9.2
cd ~/tmp/1.9.2
rbenv local 1.9.2-p320 # .ruby-versionが生成される
gem install arduino_firmata
arduino_firmata -v

で、crontabに書く
* * * * * arduino_firmata -v > $HOME/arduino_version
* * * * * cd $HOME/tmp/1.9.2 && arduino_firmata -v > $HOME/tmp/1.9.2/arduino_version

ホームディレクトリではrbenvのglobaで設定されているRuby2.0.0が使われたので、arduino_firmata gemがインストールされていなくてコマンド実行失敗していた。
tmp/1.9.2にcdした方はちゃんとRuby1.9.2に切り替わっていて、gemで入れたarduino_firmataコマンドへのパスも通っていた。
tmp/1.9.2/arduino_versionには ArduinoFirmata v0.2.8 と書かれていた。


cronで使うまとめ

アプリのディレクトリ毎に
  • crontabの一番上で PATH=$HOME/.rbenv/shims:$PATH
  • アプリ毎にGemfileを作ってbundlerでgem管理
  • アプリのディレクトリに .ruby-version作って、rbenvのバージョンも合わせる
  • アプリのディレクトリにcdで移動してから実行

これで複数バージョンのRubyをcrontabで使える。