Browse Month: September 2012

Ruby 1.8.7 + Rubygem で invalid date format in specification エラーを抑制する方法

Ruby 1.8.7(REE 2012.02)+ Rubygems で、gem をインストールするときや bundle list すると、次のようなエラーが表示されることがある。


Invalid gemspec in [/var/www/app/shared/bundle/ruby/1.8/specifications/json-
1.6.1.gemspec]: invalid date format in specification: "2011-09-18 00:00:00.000000000Z"

このエラーを抑制するには、Rubygem 1.6.2 をダウングレードすると抑制される・・・。

$ sudo /opt/ruby/bin/gem update --system 1.6.2

2012/10/01 追記:
1.8.24 もアップグレードすることで解消しますね。。。
最新版の方がいいですね。Rubygems 本体の変更履歴は、こちら
ちなみに REE 1.8.7-2012.02 バージョンに同梱されている Rubygems のバージョンは、1.8.15 ですが、1.8.22 でこの現象エラーは発生しなくなりました。

Nginx + Unicorn を導入記

とある Ruby 1.9.2 + Sinatra ベースのアプリケーションがあって、当初は大人の事情で WEBrick で本番稼働していたけれど、たまにエラーが発生することがあったので、思い切って Nginx + Unicorn はいわゆるモダンな構成(死語)に切り替えてみました。

今回のアプリケーションのルートディレクトリを SINATRA_ROOT としています。

まず、$SINATRA_ROOT/config.ru を作成します。

require 'rubygems'
require 'sinatra'

require './app.rb'
run Sinatra::Application

次に $SINATRA_ROOT/app.rb を作成します。./script/app というのは、既存の Ruby 1.9.2 + Sinatra アプリケーションです。

require './script/app'

次に、Unicorn の設定ファイルを作成します。今回は、Unicorn の設定ファイルは $SINATRA_ROOT 以下におきました。
Unicorn の設定ファイルは、Unicorn 公式サイトの設定ファイルを参考にしました。preload_app を true にするとエラーが発生したので、今回は false のままにしました。変更した設定は、次のとおりです。

  • worker_process: ワーカーのプロセス数(CPU コア数と同じにしました)
  • working_directory: アプリケーションの実行ディレクトリ
  • listen: Unix Domain Socket ファイルのパス
  • pid: プロセスIDファイルのパス
  • stderr_path, stdout_path: ログファイルのパス

アプリケーション側の設定は以上になります。
あとは、Nginx のインストールと設定です。

まずは、Nginx 公式の Yum リポジトリを追加します。(公式情報は、こちら

/etc/nginx/conf.d-local に専用の設定ファイルを作成します。

upstream example {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).

# for UNIX domain socket setups:
server unix:/var/tmp/example.sock fail_timeout=0;
}
server {
listen 443;
server_name _;
index index.html index.htm index.php;
ssl on;
ssl_certificate /etc/nginx/nginx.pem;
ssl_certificate_key /etc/nginx/nginx.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
access_log /var/log/nginx/example_access.log main;
proxy_pass http://example;
}
}

上の設定を追加して、nginx を起動します。

Unicorn 経由でアプリケーションを起動する方法ですが、これも /etc/init.d/ に専用のスクリプトを作成してみました。
Unicorn の init.d スクリプトは、この gist にあるものを参考にして作成しました。

そして、Nginx と Unicorn の init.d スクリプトを起動時に自動的に起動するように設定しました。

最後に、アプリケーションのログテーションを、logrotate.d に、次のように設定しました。

/var/log/nginx/example_access.log {
daily
missingok
rotate 30
#compress
dateext

# this is important if using "compress" since we need to call
# the "lastaction" script below before compressing:
#delaycompress

# note the lack of the evil "copytruncate" option in this
# config. Unicorn supports the USR1 signal and we send it
# as our "lastaction" action:
lastaction
pid=/var/run/example.pid
test -s $pid && kill -USR1 "$(cat $pid)"
endscript
}

Nginx + Unicorn、なかなか便利な構成だと思いますね。

XCode 4.5 + RVM のインストール方法

XCode 4.5 がリリースされました。恒例の RVM のインストール方法です。

1. XCode 4.5 + Command Line Tools をインストールします

2. Homebrew 経由で、apple-gcc42 をインストールします

$ brew update
$ brew tap homebrew/dupes
$ brew install apple-gcc42

3. RVM を、通常通りにインストールします(公式情報はこちら

$ curl -L https://get.rvm.io | bash -s stable

4. RVM を設定します、zshrc に次のような記述を追加します、iTerm2 を使っている場合で、Profiles – General – Working Directory の設定で「Reuse previous sessions’s directory」を設定している場合は、__rvm_project_rvmrc を .zshrc に追加しましょう。

[[ -s $HOME/.rvm/scripts/rvm ]] && source $HOME/.rvm/scripts/rvm
[[ -s $HOME/.rvm/scripts/rvm ]] && [[ $TERM_PROGRAM == "iTerm.app" ]] && __rvm_project_rvmrc

5. REE をインストールするには、次のコマンドでインストールすることができます、同じように 1.9.2 / 1.9.3 のインストールも可能です

$ CC=gcc-4.2 rvm install ree-1.8.7-2012.02 --enable-shared --without-tk --without-tcl

MySQL 5.5 + mysql2 gems でエラーが発生する件について

CentOS 6.3 x86_64 の MySQL 5.5 の環境(MySQL 5.5 は、公式の RPM を使用)で、gem install mysql2 すると、次のエラーが発生します。

$ sudo gem install mysql2
Building native extensions. This could take a while...
ERROR: Error installing mysql2:
ERROR: Failed to build gem native extension.
/usr/bin/ruby extconf.rb
checking for rb_thread_blocking_region()... no
checking for rb_wait_for_single_fd()... no
checking for mysql.h... yes
checking for errmsg.h... yes
checking for mysqld_error.h... yes
creating Makefile
make
gcc -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -DHAVE_MYSQL_H -DHAVE_ERRMSG_H -DHAVE_MYSQLD_ERROR_H -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -fPIC -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -DMY_PTHREAD_FASTMUTEX=1 -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing -fPIC -Wall -funroll-loops -c mysql2_ext.c
./client.h:16: warning: ‘rb_thread_blocking_region’ defined but not used
gcc -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -DHAVE_MYSQL_H -DHAVE_ERRMSG_H -DHAVE_MYSQLD_ERROR_H -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -fPIC -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -DMY_PTHREAD_FASTMUTEX=1 -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing -fPIC -Wall -funroll-loops -c result.c
gcc -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -DHAVE_MYSQL_H -DHAVE_ERRMSG_H -DHAVE_MYSQLD_ERROR_H -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -fPIC -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -DMY_PTHREAD_FASTMUTEX=1 -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing -fPIC -Wall -funroll-loops -c client.c
gcc -shared -o mysql2.so mysql2_ext.o result.o client.o -L. -L/usr/lib64 -L. -rdynamic -Wl,-export-dynamic -Wl,-rpath,/usr/lib64 -lruby -L/usr/lib64 -lmysqlclient_r -lpthread -lm -lrt -ldl -lpthread -lrt -ldl -lcrypt -lm -lc
/usr/bin/ld: cannot find -lmysqlclient_r
collect2: ld returned 1 exit status
make: *** [mysql2.so] Error 1

どうやら、mysqlclient_r が見つからないようです。export LD_LIBRARY_PATH=/usr/lib64/mysql/:/usr/lib64 したり、/etc/ld.so.conf.d/ に mysql.conf を作成して /usr/lib64/mysql を作成してみたのですが、同じエラーのままでした。

MySQL 5.5 から、mysqliclient_r ではなく、mysqlclient になったようで、ちょうど先月に mysql2 gem のコミットが入っていました。
このバージョンは、まだ正式リリースされておらず、現在のバージョンは 0.3.12b4 となっています。そろそろ、リリースされそうな雰囲気なのですが、正式リースでないと不安のため、/usr/bin/mysql_config を書き換えることにしました。

差分は、次のとおりです。

--- mysql_config-org 2012-09-18 17:10:53.083571150 +0900
+++ mysql_config 2012-09-18 17:13:36.359551034 +0900
@@ -83,7 +83,7 @@
bindir='/usr/bin'

# If installed, search for the compiled in directory first (might be "lib64")
-pkglibdir='/usr/lib64'
+pkglibdir='/usr/lib64/mysql'
pkglibdir_rel=`echo $pkglibdir | sed -e "s;^$basedir/;;"`
fix_path pkglibdir $pkglibdir_rel lib/mysql lib

@@ -112,7 +112,7 @@
# We intentionally add a space to the beginning and end of lib strings, simplifies replace later
libs=" $ldflags -L$pkglibdir -lmysqlclient -lpthread -lm -lrt -ldl "
libs="$libs "
-libs_r=" $ldflags -L$pkglibdir -lmysqlclient_r -lpthread -lm -lrt -ldl "
+libs_r=""
embedded_libs=" $ldflags -L$pkglibdir -lmysqld -lpthread -lm -lrt -lcrypt -ldl -laio "

if [ -r "$pkglibdir/libmygcc.a" ]; then
@@ -121,7 +121,7 @@
# automatically. We package the libmygcc.a from the build host, to provide
# definitions for those. Bugs 4921, 19561, 19817, 21158, etc.
libs="$libs -lmygcc "
- libs_r="$libs_r -lmygcc "
+ libs_r=""
embedded_libs="$embedded_libs -lmygcc "
fi

この状態にして、次のコマンドを実行すれば、取り急ぎmysql2 gem をインストールすることができます。

$ sudo gem install mysql2 -- --with-mysql-config=/usr/bin/mysql_config
Building native extensions. This could take a while...
Successfully installed mysql2-0.3.11
1 gem installed
Installing ri documentation for mysql2-0.3.11...
Installing RDoc documentation for mysql2-0.3.11...

なお、かなり無理矢理の対応のため、くれぐれも /usr/bin/mysql_config の書き換えには、他に何らかの悪影響があるかもしれないので、ぐれぐれもご注意下さい・・・。