[Sy] Amazon EMRでRubyのTime::to_dateメソッドは使えないので注意
2014/07/11
最近 AWSの EMR(Elastic MapReduce) をHadoop streamingで使ってるんですが、Rubyのバージョンがどうやら1.8系らしく、Rubyを2.0系から始めたぼくが見事にハマったという話。
まず、何が起きたのか?
EMRで実行したいmapperをローカルで走らせたらうまくいくんですが、何故かEMR上ではコケる。
原因は?
mapperの中でタイムスタンプを年月日に変換する処理をこう書いてたんですね。
require 'date'
.
.
.
# 例えば、tm = Time.at(1405036212) みたいなTimeオブジェクト
dt = tm.to_date
ちなみにこの時ローカルのRubyのバージョンは2.1.1で、この場合だとdt = '2014-07-11'
となります。
これをそのままEMRで動かそうとするとコケるわけですが、なんでも EMRのRubyのバージョンは1.8系らしく、1.8系では先ほどのTime::to_date
というメソッドがprivate だという罠。
なので、おとなしく以下のように書き直したらうまくいきました。
dt = tm.strftime('%Y-%m-%d')
・・・たぶん、昔からRubyやってる人はこんなミスはしないかと思いますが。そもそもEMRはなんでそんなに古いバージョンなのかと。
試しにローカルに1.8系を入れてテスト
試しに、以下のコードtest.rb
を用意して、rbenvで2.1.1と1.8.7-p375の動きを比べてみます。
require 'date'
tm = Time.at(1405036212)
puts "strftime : #{tm.strftime('%Y-%m-%d')}"
puts "to_date : #{tm.to_date}"
まずは2.1.1で実行。
$ /usr/local/var/rbenv/versions/2.1.1/bin/ruby test.rb
strftime : 2014-07-11
to_date : 2014-07-11
問題なく、両方ともうまくいきました。
次に1.8.7-p375で実行。
strftime : 2014-07-11
test.rb:5: private method `to_date' called for Fri Jul 11 08:50:12 +0900 2014:Time (NoMethodError)
strftime
の方は問題ないですが、to_date
の方は「privateメソッドのto_dateが呼ばれたよ!」と狙い通りエラーになりました。
ひとこと
やっぱHadoop使うならJavaがいいのかな?