プログラマでありたい

おっさんになっても、プログラマでありつづけたい

複数並行可能なRubyのクローラー、「cosmicrawler」を試してみた

 最近のRubyのクローラーは、EventMachineを使って並列化するのが流行のようです。EventMachineは、非同期処理をお手軽に実装できるフレームワークです。Rubyのスレッド機能との違いは、Reactorパターンを使いシングルスレッドで実装している点です。こちらのブログが詳しいので参考になります。 「見えないチカラ: 【翻訳】EventMachine入門
 EventMachineを使うと、イベント・ドリブンの処理を簡単に実装出来ます。使い方は簡単ですが、通常の同期処理やスレッドをつかった処理に比べると、どうしてもコードの記述量は多くなります。今回の例である並列化してクローラーを走らせるという用途であれば、短時間で多くのサイトにアクセスするのが目的です。イベント・ドリブンで並列化処理を実装するのが目的ではないはずです。その辺りの面倒くさい処理を実装したライブラリがcosmicrawlerです。中身の実装を見てみると、非常にシンプルで解りやすいです。通り一遍ですが、インストールして試してみました。

cosmicrawlerのインストールとサンプルソース



 まずはcosmicrawlerのインストールですが、gem install cosmicrawlerだけで出来ます。直接依存するモジュールとしては、eventmachineとem-http-request、em-synchronyの3つです。付随的にaddressable、cookiejar、em-socksify、http_parserがインストールされます。

 それでは、サンプルソースを見てみましょう。公式にあったサンプルの取得先を、はてなのURLに変えただけです。

require 'cosmicrawler'

Cosmicrawler.http_crawl(%w(http://b.hatena.ne.jp/hotentry/it http://b.hatena.ne.jp/hotentry/life)) {|request|
  get = request.get
  puts get.response if get.response_header.status == 200
}

 実行してみると、すぐに結果が出てくると思います。取得するURLの付与の部分を作りこめば、すぐに使えそうな印象です。

クローラーの機能を考える



 前回、Masqueを紹介しました。Masqueは、Capybaraを使いJavaScriptの画面にも対応出来るというのが特徴です。今回のcosmicrawlerは、並列処理で高速化できるのが特徴です。どちらも、データを取得するという機能に特化したクローラーです。


 クローラーの主な機能としては、以下の3つがあります。

  • データ取得 … データをダウンロードする機能。robots.txtに従うかの判断も必要。
  • データ解析 … HTMLをパースする機能。HTML中からリンクを抽出して、再帰処理などにも利用する
  • データ保存 … 取得したデータを保存する機能。ファイルの他に、RDBMSやNoSQLを使うパターンもある。


 上記の機能を全て揃えているRubyのクローラーのライブラリとしては、今のところはanemoneしか知りません。一方で、データ取得以外の部分については、それぞれのクローラーが独自で実装する必要性は薄いです。例えば、robots.txtで禁止されているかのチェックは専用のライブラリがあれば良いし、HTML中からURLを抜き出して再帰処理する部分もライブラリとして外出し出来そうです。またHTML解析の部分も、NokogiriなどのHTMLパースのライブラリを使うことが多いです。この辺りを疎結合に使えるパターンを思案中です。あるいはAnemoneをクローラーのフレームワークとみなして、データ取得部分のみを切り替えられるように変更を加えるのも面白いかもしれませんね。


See Also:
オープンソースのRubyのWebクローラー"Anemone"を使ってみる
JavaScriptにも対応出来るruby製のクローラー、Masqueを試してみる
あらためてRuby製のクローラー、"anemone"を調べてみた


参照:
Rubyで複数並行なクローラをすっきりと書けるライブラリ「cosmicrawler」をgemとして公開した
見えないチカラ: 【翻訳】EventMachine入門
PythonとかScrapyとか使ってクローリングやスクレイピングするノウハウを公開してみる! - orangain flavor


Rubyによるクローラー開発技法

Rubyによるクローラー開発技法

Spidering hacks―ウェブ情報ラクラク取得テクニック101選

Spidering hacks―ウェブ情報ラクラク取得テクニック101選

JavaScriptにも対応出来るruby製のクローラー、Masqueを試してみる

 ちょっと前に試そうと思って、そのまま放置していたruby製のクローラー「Masque」を試してみました。ruby製のクローラーは、他にはAnemoneという優秀なものがあります。その上で何故というと、Anemoneにはない特性があるからです。
 MasqueはCapybaraのDSLで記述出来るWebクローラーです。つまりCapybaraを動かす為のものなので、JavaScriptも解釈が出来るということです。また場合によっては、レスポンシブルデザインのサイトの確認も出来ます。一方で、Anemoneはあくまで個別個別のHTMLを取得する為のクローラーなので、JavaScriptを多用しているサイトでの情報取得に向きません。どちらが優れているという訳ではないので、用途に応じて使いこなせばよいでしょう。

Masqueのインストール


$ gem install masque
Fetching: headless-1.0.1.gem (100%)
Successfully installed headless-1.0.1
Fetching: mini_portile-0.5.2.gem (100%)
Successfully installed mini_portile-0.5.2
Fetching: nokogiri-1.6.1.gem (100%)
Building native extensions.  This could take a while...
Successfully installed nokogiri-1.6.1
Fetching: mime-types-2.0.gem (100%)
Successfully installed mime-types-2.0
Fetching: rack-1.5.2.gem (100%)
Successfully installed rack-1.5.2
Fetching: rack-test-0.6.2.gem (100%)
Successfully installed rack-test-0.6.2
Fetching: xpath-2.0.0.gem (100%)
Successfully installed xpath-2.0.0
Fetching: capybara-2.1.0.gem (100%)
IMPORTANT! Some of the defaults have changed in Capybara 2.1. If you're experiencing failures,
please revert to the old behaviour by setting:

    Capybara.configure do |config|
      config.match = :one
      config.exact_options = true
      config.ignore_hidden_elements = true
      config.visible_text_only = true
    end

If you're migrating from Capybara 1.x, try:

    Capybara.configure do |config|
      config.match = :prefer_exact
      config.ignore_hidden_elements = false
    end

Details here: http://www.elabs.se/blog/60-introducing-capybara-2-1

Successfully installed capybara-2.1.0
Fetching: capybara-webkit-1.0.0.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing masque:
	ERROR: Failed to build gem native extension.

    /Users/username/.rvm/rubies/ruby-2.0.0-p247/bin/ruby extconf.rb
Command 'qmake -spec macx-g++' not available


Gem files will remain installed in /Users/username/.rvm/gems/ruby-2.0.0-p247@masque/gems/capybara-webkit-1.0.0 for inspection.
Results logged to /Users/username/.rvm/gems/ruby-2.0.0-p247@masque/gems/capybara-webkit-1.0.0/./gem_make.out


qmakeがないとエラーが出ます。インストール方法を探してみると、Homebrewでインストール出来るようです。パッケージ名は、qmakeではなくqtです。

$ brew install qt
Warning: Building source; cellar of qt's bottle is /usr/local/Cellar
==> Downloading http://download.qt-project.org/official_releases/qt/4.8/4.8.5/qt
######################################################################## 100.0%
==> ./configure -prefix /Users/username/tools/homebrew/Cellar/qt/4.8.5 -system-zli
==> make
==> make install
==> Caveats
We agreed to the Qt opensource license for you.
If this is unacceptable you should uninstall.
==> Summary
🍺  /Users/username/tools/homebrew/Cellar/qt/4.8.5: 2778 files, 119M, built in 23.6 minutes

コマンド一発でインストール出来るのですが、割と時間が掛かります。


気を取り直して、再度gemでmasqueのインストール

$ gem install masque
Building native extensions.  This could take a while...
Successfully installed capybara-webkit-1.0.0
Fetching: http_parser.rb-0.5.3.gem (100%)
Building native extensions.  This could take a while...
Successfully installed http_parser.rb-0.5.3
Fetching: eventmachine-1.0.3.gem (100%)
Building native extensions.  This could take a while...
Successfully installed eventmachine-1.0.3
Fetching: faye-websocket-0.4.7.gem (100%)
Building native extensions.  This could take a while...
Successfully installed faye-websocket-0.4.7
Fetching: poltergeist-1.3.0.gem (100%)
Successfully installed poltergeist-1.3.0
Fetching: masque-0.3.1.gem (100%)
Successfully installed masque-0.3.1
Parsing documentation for capybara-webkit-1.0.0
Installing ri documentation for capybara-webkit-1.0.0
Parsing documentation for eventmachine-1.0.3
unable to convert "\xCF" from ASCII-8BIT to UTF-8 for lib/fastfilereaderext.bundle, skipping
unable to convert "\xCF" from ASCII-8BIT to UTF-8 for lib/rubyeventmachine.bundle, skipping
Installing ri documentation for eventmachine-1.0.3
Parsing documentation for faye-websocket-0.4.7
unable to convert "\xCF" from ASCII-8BIT to UTF-8 for lib/faye_websocket_mask.bundle, skipping
Installing ri documentation for faye-websocket-0.4.7
Parsing documentation for http_parser.rb-0.5.3
unable to convert "\xCF" from ASCII-8BIT to UTF-8 for lib/ruby_http_parser.bundle, skipping
Installing ri documentation for http_parser.rb-0.5.3
Parsing documentation for masque-0.3.1
Installing ri documentation for masque-0.3.1
Parsing documentation for poltergeist-1.3.0
Installing ri documentation for poltergeist-1.3.0
6 gems installed


今回はすんなりインストール出来ます。早速サンプルソースを走らせてみましょう。サンプルソースは以下の通りです。

require "masque"
m = Masque.new(:display => 99, :driver => :webkit) # or :driver => :poltergeist
m.run do
  # Capybara::DSL syntax
  # https://github.com/jnicklas/capybara#the-dsl

  visit "http://www.google.com/"
  fill_in("q", :with => "capybara")
  find('*[name="btnG"]').click

  titles = evaluate_script <<-JS
    (function(){
      var titles = Array.prototype.map.call(
        document.querySelectorAll('h3 a'),
        function(a) {
          return a.innerText;
        }
      );

      return titles;
    })();
  JS
  puts titles.join("\n")
end


サンプルソースを実行してみると、下記のようなエラーが出ました。Xvfbがないとのことです。Xvfbは仮想フレームバッファで、Xを起動していないマシンでもXの仮想的なXフレームバッファを使えるようにする為のものです。これを入れておけば、Xのライブラリが使えるようになります。

$ ruby masque_sample.rb 
/Users/username/.rvm/gems/ruby-2.0.0-p247@masque/gems/headless-1.0.1/lib/headless/cli_util.rb:9:in `ensure_application_exists!': Xvfb not found on your system (Headless::Exception)
	from /Users/username/.rvm/gems/ruby-2.0.0-p247@masque/gems/headless-1.0.1/lib/headless.rb:68:in `initialize'
	from /Users/username/.rvm/gems/ruby-2.0.0-p247@masque/gems/masque-0.3.1/lib/masque.rb:50:in `new'
	from /Users/username/.rvm/gems/ruby-2.0.0-p247@masque/gems/masque-0.3.1/lib/masque.rb:50:in `initialize'
	from masque_sample.rb:2:in `new'
	from masque_sample.rb:2:in `<main>'


 さてどうしたものかと考えたのですが、基本的にはXがあれば良いはずです。MacでXはどうなっているかというと、入っていないのでXQuartzを使えと公式ページに書いています。XQuartzはdmg形式で配布されてるので、ダウンロードしてインストールしましょう。インストール後に再起動して環境を反映さえます。


 再度、実行してみます。何やら結果が出ていますね。これは、masqueがGoogleでcapybaraを指定して検索ボタンを押して、その結果を取得しているのです。

$ ruby masque_sample.rb 
jnicklas/capybara &#183; GitHub
capybara の画像検索結果
Capybara - Wikipedia, the free encyclopedia
フレームワークで実践! JavaScriptテスト入門(5):Capybara ...
capybara で快適なテスト生活を - SlideShare
Capybara Games
Capybara - GitHub Pages
Capybara の README 意訳 - おもしろWEBサービス開発日記
Capybara Madness
RSpecとCapybaraでJavaScript/Ajaxをテストする - Rails 雑感 - Ruby ...
capybara | RubyGems.org | your community gem host

Masqueの構造



 最初に書いた通り、MasqueはCapybaraのDSLを記述出来るクローラーです。それを念頭にソースを見ると、以下のソースの意味が直ぐ解ります。

  visit "http://www.google.com/"
  fill_in("q", :with => "capybara")
  find('*[name="btnG"]').click


 とここまで書いて、Capybaraとの違いが気になってきます。同じ処理をCapybaraで書くと、下記のようなソースになります。

require 'capybara'
require 'capybara-webkit'

include Capybara::DSL

Capybara.default_driver = :webkit
visit "http://www.google.com/"
fill_in("q", :with => "capybara")
find('*[name="btnG"]').click

titles = evaluate_script <<-JS
  (function(){
    var titles = Array.prototype.map.call(
      document.querySelectorAll('h3 a'),
      function(a) {
        return a.innerText;
      }
    );

    return titles;
  })();
JS
puts titles.join("\n")

 DSLの宣言など、一部の違いがあるだけです。結論としては、MasqueはCapybaraのラッパーとして一部の値を上書きして使いやすくしているだけです。CapybaraのDSLを使いますよという時点で、そりゃそうだという結論です。

まとめ



 結論的には、Capybaraの構造をちゃんと知っていれば、特に必要のないライブラリです。一方でMasqueを使うことによって、余計な宣言の手間も必要なくなります。また必要なところは上書きで設定できるようになっています。まぁ使っても良いかなぁというレベルです。方向性としては、Capybaraの設定を便利にするより、クローラーとしての機能を盛り込んだ方が面白いと思います。リンクを解析して再帰的に情報を収集する機能などを、付加するのも1つだと思います。


See Also:
オープンソースのRubyのWebクローラー"Anemone"を使ってみる
複数並行可能なRubyのクローラー、「cosmicrawler」を試してみた
あらためてRuby製のクローラー、"anemone"を調べてみた


参照:
About X11 and OS X
XQuartz
uu59/masque · GitHub
jnicklas/capybara · GitHub


Rubyによるクローラー開発技法

Rubyによるクローラー開発技法

Spidering hacks―ウェブ情報ラクラク取得テクニック101選

Spidering hacks―ウェブ情報ラクラク取得テクニック101選

TwilioとAmazon SNSを組み合わせて、電話で自動通知

 今年の4月にTwilioのアカウントをとって早8ヶ月。これは色々なことに使えるとワクワクしながら、すっかり放置していました。日本ではKDDIさんと組んで展開し、色々な所でハンズオンなども開催されていたので、知名度的にも手軽に使える音声APIのデファクトになりつつあるのではないでしょうか?簡単ながらTwilioの紹介とユースケースを考えみます。

Twilioから電話を掛けてみる



 アカウントと電話番号の取り方は忘れました。アカウントは本家とKDDI経由での取り方あるようです。私は本家の方でとっています。APIの使い方は色々なところで載っていてあまり悩むことはないと思いますが、おさらいを含めてまとめておきます。


rubyで電話を掛けるサンプル
make_call.rb

require 'rubygems'
require 'twilio-ruby'

@account_sid = 'Your Account SID'
@auth_token = 'Your Account auth token'

# set up a client to talk to the Twilio REST API
@client = Twilio::REST::Client.new(@account_sid, @auth_token)


@account = @client.account
@call = @account.calls.create(
{
    :from => '+twilio phone number',
    :to => '+your phone number',
    :method => 'GET',
    :status_callback_method => 'GET',
    :url => 'https://s3-ap-northeast-1.amazonaws.com/examples-misc/sample_response.xml'
})
puts @call


sample_response.xml

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say language="ja-jp">Twilioからの自動メッセージ。電話番号の停止を忘れずにお楽しみください。</Say>
</Response>

 urlで電話のメッセージの設定を行います。MethodはGetでも大丈夫なので、適当なところに静的ファイルをおいておけば大丈夫です。このサンプルのURLも暫くおいておくので、試しに使って貰っても構いません。


 早速試してみましょう。エラーが出なければ、電話が掛かってくるはずです。languageを日本語に設定しておけば、ちゃんと日本語で読み上げてくれます。

$ ruby make_call.rb 
#<Twilio::REST::Call:0x007feaa538beb8>

AWSと連携したユースケースを考える



 Twilioのユースケースは何でしょうか?色々ありますが、例えば障害監視にも使えます。メールやその他の方法は沢山あるにしても、電話で通知して欲しいというシチュエーションはまだまだあります。また、誰か一人だけに連絡するのではなく、電話に出なければ優先順位に従ってコールして欲しいというのはあります。TwilioのAPIを使えば、プログラミングで実装できます。
 サンプルにAWSの障害検知のパターンを書いてみました。AWS側の障害検知はSNSを使い、SNSからHTTP通知でサーバに送りTwilioAPIを叩くパターンと、SNSからSQSで通知しサーバからSQSのキューをポーリングし続けるパターンです。ケースバイケースで使い分ければと思います。HTTPの場合は、HTTP通知を受けるサーバの冗長性を考える必要があります。HTTPなので、通知を受け取ったかの管理が出来ないところが辛いです。SQSパターンの方は、ポーリングを受ける方の稼働の担保が必要です。一方で通知を受け取ったかの管理はキューを見れば解るので楽ですね。

注意点



 電話番号を取得していると、毎月$5掛かります。残高が足りなくなると、アカウントはロックされます。更に恐ろしいことに、ロック中も毎月$5課金され続けます。つまりマイナスになります。私は冒頭に書いてある通り、半年以上ぶりにログインしました。するとアカウントがロックされている旨が出ていたので、仕方がないので$20をチャージしました。しかし、何故かそれでも残高がマイナスの状態に。課金履歴を見てると使っていない間もロックされている間も、毎月課金され続けていました。やむなく再度$20のチャージ。つまりこのエントリーを書くために$40かかっています。不要な電話番号は開放するのをお忘れずに。Twilio本家サイトであれば、電話番号はNumbersで該当の番号を選んでRelease Numberを選ぶと開放できます。これだけは覚えておいてください。骨身にしみました。

Jenkinsでビルド・パイプラインを構築する

 前回、Jenkinsのインストールについて書きました。今回は、Jenkinsでビルド・パイプラインを構築する話です。

ビルド・パイプラインとは?



 ビルド・パイプラインとは、ビルドのプロセスを分割して順番に実行していくことです。例えばビルドの流れとして、コミット→静的解析→コンパイル→ロジック層のユニットテスト→UI層のユニットテスト等があったとします。これを1つのジョブとして登録するのではなく、1つ1つのジョブとして実行し、成功した場合のみ次のステップに進めるようにします。これがビルドパイプラインです。
 メリットとしては、どの工程で失敗しているのか解りやすいことが第一にあります。またJenkinsの特性を活かして、特定のジョブを並列で動かしたり出来るので効率化も出来ます。また、更に検証済みマージなど、高度な活用にもつながります。

Jenkinsでビルド・パイプラインの構築



 元々Jenkinsでは、ジョブの前後関係を簡単に作れます。ビルド・トリガで"他プロジェクトのビルド後にビルド"を指定するだけです。


 しかし、これだけでは前後関係が解りにくいですし、視覚的に楽しくないです。そこで、Jenkin Build Pipeline プラグインの登場です。このプラグインは、基本的には既存のJenkinsのジョブの前後関係を視覚的に表現するだけです。副作用もなく、かつ格段に使いやすくなります。

ビルド・パイプラインの設定



 Jenkin Build Pipeline プラグインをインストールすると、ダッシュボードからパイプラインを作れます。"Build Pipeline View"か"リストビュー"を作れます。せっかくなので視覚的なBuild Pipeline Viewが良いですね。
 作成後に、Select Initial Jobで最初に実行するジョブを選びます。基本的にはこれだけです。Inital Jobで選んだジョブの依存関係に従いパイプラインが形成されます。実行すると失敗しない限り順番にジョブが実行されていきます。

手動のトリガー設定



 またBuild Pipeline プラグインは、手動のトリガーを設定できます。ビルドやユニットてすとは、自動でどんどん進んでも問題ありません。でも例えば検証環境や本番環境へのリリースのジョブなどは、自動で行われたら困る場合が多いです。その場合は、手動でのトリガーを設定します。
 プラグインをインストールすると、ビルド後の処理にBuild Pipeline DownStream Project Namesが設定できます。これが手動で実行する後続ジョブです。

まとめ



 ビルドパイプライン・プラグイン1つ入れるだけで、随分と使いやすくなりました。やっぱり視覚化は楽しくて良いですよね。また、あまりJenkinsに詳しくない人でも、直感的に役割が理解出来るのが良いと思います。次は、Selenium・Chefとの連携や、検証マージの話を書きたいと思います。


See Also:
Amazon Linux AMIにRuby用にJenkinsをインストールする
JenkinsとSelenium WebDriverでUI層のテストも自動化&永続化する


参照:
Jenkinsでビルド・パイプラインを作る | Ryuzee.com



Amazon Linux AMIにRuby用にJenkinsをインストールする


 HudsonもといJenkinsは昔からよく使っていますが、全くそれに関するエントリーをあげていないことに気がつきました。ということで、暫くJenkins強化週間です。まずはお決まりのインストールメモから。Java用だと一瞬で終わってしまうので、Rubyで使用することを想定しています。

RVMのインストール



Amazon Linux AMIでRubyであれば、何はなくてもRVMをインストールします。yumでインストールするリポジトリについては、もう少し絞れると思います。

$ sudo su -
# yum -y install git
# yum -y groupinstall "Development Tools"
# yum -y groupinstall "Development Libraries"
# yum -y install libxslt-devel
# yum -y install sqlite-devel
# yum -y install libyaml-devel
# \curl -L https://get.rvm.io | bash -s stable --ruby
# echo '[[ -s "/usr/local/rvm/scripts/rvm" ]] && . "/usr/local/rvm/scripts/rvm" # Load RVM function' >> /etc/bashrc
# source /etc/bashrc
# yum -y install rake

 ちなみにruby2.0リリース以降、rvmは2.0をデフォルトでインストールするようになりました。

jenkinsユーザでの設定



 正しい手順(※)か自信はないのですが、jenkinsユーザでrvmの設定をする必要があります。yumでインストールした場合、jenkinsユーザは、ログイン出来なくなっています。/etc/passwdを編集してログイン出来るようにします。その後に、rvmとrakeをインストールします。
※管理設定のところのrakeの設定をどうしても読んでくれないのです。

jenkins:x:220:499:Jenkins Continuous Build server:/var/lib/jenkins:/bin/false

jenkins:x:220:499:Jenkins Continuous Build server:/var/lib/jenkins:/bin/bash

$ rvm install 1.9.3
$ rvm default 1.9.3
$ rvm use 1.9.3
$ gem install rake

Jenkinsのインストール



 Jenkinsは、Javaで動きます。更にバイナリーの場合、JavaのAppサーバーが含まれています。ですので、簡単にインストール&起動出来ます。

sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum -y install jenkins


起動&自動起動の設定

sudo service jenkins start
sudo chkconfig jenkins on

Ruby用のプラグインのインストール



 Jenkins起動後にWebのUIから、Rubyのプラグインをインストールします。最低限必要なのが、ruby,rvm,rakeのプラグインです。他にあった方が良いプラグインとしては、ruby metricsやgit client,GitHub API Pluginを入れておくと幸せになれると思います。インストールに成功していたら、8080ポートでアクセス出来るはずです。
http://your_ec2_address:8080/
 アクセス後に、"Jenkinsの管理->プラグインの管理"で必要なプラグインをインストールします。

Rake plugin
Ruby Plugin
RVM Plugin

Railsプロジェクトの作成とJenkinsのジョブ登録



 通常通りRailsプロジェクトを作成後、Git等でバージョン管理してください。リポジトリ作成後に、Jenkinsのプロジェクト作成を行います。フリースタイル・プロジェクトのビルドで、ジョブ名を適当につけます。

 設定画面で詳細の設定を行います。まずはリポジトリの参照。任意のリポジトリを指定してください。今回は、GitHubを使っています。

 Rubyの指定も行います。

プロジェクトの設定



 どうやっても、RVMプラグイン経由でのInvoke Rakeが実行出来ないので、シェルの実行で行うことに。

source /var/lib/jenkins/.bashrc
which bundle || gem install bundler
bundle install
bundle exec rake db:migrate
bundle exec rake

トラブルシューティング



Rakeプラグインでrakeが実行出来ない。こちらは、グローバルの設定画面でrakeのパスを指定することで解決します。

Using /var/lib/jenkins/.rvm/gems/ruby-1.9.3-p392
[workspace] $ rake spec
FATAL: rake execution failed
java.io.IOException: Cannot run program "rake" (in directory "/var/lib/jenkins/jobs/ビルド/workspace"): java.io.IOException: error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:475)
at hudson.Proc$LocalProc.(Proc.java:244)
at hudson.Proc$LocalProc.(Proc.java:216)
at hudson.Launcher$LocalLauncher.launch(Launcher.java:763)
at hudson.Launcher$ProcStarter.start(Launcher.java:353)
at hudson.Launcher$ProcStarter.join(Launcher.java:360)
at hudson.plugins.rake.Rake.perform(Rake.java:141)
at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:19)
at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:814)
at hudson.model.Build$BuildExecution.build(Build.java:199)
at hudson.model.Build$BuildExecution.doRun(Build.java:160)
at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:593)
at hudson.model.Run.execute(Run.java:1567)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:46)
at hudson.model.ResourceController.execute(ResourceController.java:88)
at hudson.model.Executor.run(Executor.java:237)
Caused by: java.io.IOException: java.io.IOException: error=2, No such file or directory
at java.lang.UNIXProcess.(UNIXProcess.java:164)
at java.lang.ProcessImpl.start(ProcessImpl.java:81)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:468)
... 15 more
Build step 'Invoke Rake' marked build as failure
Finished: FAILURE


Rakeプラグインでrakeが実行出来ない。その2。今のところ解決策が解っていません。誰か教えてください。

[workspace] $ /var/lib/jenkins/.rvm/rubies/ruby-1.9.3-p392/bin/rake spec
/var/lib/jenkins/.rvm/rubies/ruby-1.9.3-p392/bin/rake:34:in `require': no such file to load -- rake (LoadError)
from /var/lib/jenkins/.rvm/rubies/ruby-1.9.3-p392/bin/rake:34
Build step 'Invoke Rake' marked build as failure
Finished: FAILURE

まとめ



 JenkinsはJava用のものとの印象が強いですが、Jenkinsは汎用の継続的インテグレーションツールです。プラグインも充実して安定しているので、是非トライしてみましょう。継続的デリバリーの第一歩は、CIの導入だと思います。


See Also:
Amazon Linux AMIにGit + Gitolite + Gitlabをインストールして、プライベートGitHubを構築する
Amazon-LinuxにRVMを利用してApache+Passenger+Railsのインストール
Jenkinsでビルド・パイプラインを構築する


参照:
Installing Jenkins on Red Hat distributions - Jenkins - Jenkins Wiki
Rubyアソシエーション: Jenkins
Jenkins CIでRSpecを自動実行する - どっかのBlogの前身のような



AWS SDK for RubyでS3の操作をする

AWS SDK for Rubyでのファイル関係のS3の操作です。一覧取得とファイルの取得の方法をメモ程度にまとめています。一覧取得については、基本的には2通りあってBucket.as_treeからツリー形式で取得する方法とBucket.objects.collectからキーの一覧を取得する方法があります。S3の構造をよくよく見てみると、フラット構造のものを擬似的にツリー構造にしているだけのようです。Bucket.objects.collectからフィルターして取得するのが効率が良いかもしれません。

require 'aws-sdk'

AWS.config({
  :access_key_id => 'your_access_key_id',
  :secret_access_key => 'your_secret_access_key',
})
s3 = AWS::S3.new

bucket = s3.buckets['yourbucketname']
tree = bucket.as_tree

#ディレクトリ一覧
directories = tree.children.select(&:branch?).collect(&:prefix)
directories.each{|directory|
  puts directory
}

#ファイル一覧
files = tree.children.select(&:leaf?).collect(&:key)
files.each{|file|
  puts file
}


#キー一覧(ファイル&ディレクトリ一覧)
puts "keys"
keys = bucket.objects.collect(&:key)
keys.each{|key|
  puts key
}


#サブフォルダ以下のファイルの一覧表示
puts "sub folder"
tree = bucket.as_tree({:prefix => 'subfoldername/'})
files = tree.children.select(&:leaf?).collect(&:key)
files.each{|file|
  puts file
}


 オブジェクトの取得

s3 = AWS::S3.new
obj = s3.buckets['yourbucketname'].objects['filename']
#ファイルの書き込み
obj.write('Hello World!')
#パス指定でファイルの書き込み
obj.write(:file => path_to_file)
#ファイルの読み込み
obj.read
#認証付きURLの発行
puts obj.url_for(:read, :expires => 60) #seconds


 後はStreamingアップロードや暗号化など色々な機能あります。公式のドキュメントを読めばひと通り書いてあるので、是非ご一読ください。


参照:
AWS SDK for Ruby


Mac OS 10.7(lion)にNetBeansのインストール

 久々にRuby On Railsで開発をしようとNetBeansを使おうとしました。新しくしたMacbook Proにはインストールしていなかったので、ダウンロードしてインストールしようとしました。プラグイン等の関係で、7.0.1をダウンロードしてウィザードに従っていると、下記のようなエラーが出ました。

NetBeans 7.0.1はこのディスクにインストールできません。このソフトウェアは、Java 6 がある時のみインストールでき動作します。


確認したところ、下記のように1.6をインストールしています。

$ java -version
java version "1.6.0_33"
Java(TM) SE Runtime Environment (build 1.6.0_33-b03-424-11M3720)
Java HotSpot(TM) 64-Bit Server VM (build 20.8-b03-424, mixed mode)

 なにがダメだったんでしょうか?ちょこっと調べていて解りませんでした。


 しかたがないので、JDK7と同梱のNetBeansが配布されてたのでそちらを使うことにしました。
 NetBeans7.2の場合、公式のRailsプラグインは配布されていません。ただ有志によるコミュニティによって作成されたモノで代用することが可能です。NetBeansを立ちあげて、ツール->プラグインを選択し、設定で下記のURLを追加します。
https://blogs.oracle.com/geertjan/resource/nb-72-community-ruby.xml

 その後、使用可能なプラグインからRubyを選び、Ruby On Railsをインストールします。これで、Mac NetBeansでRailsの開発が可能となります。 Enjoy!!