2017年09月06日(Wed) 朝からちゃんとした雨 [同日]
● [tDiary] 自作のネイティブRubyライブラリをCGIから使う
このtDiaryはNet BSD上で動いていて、ここのところコードの更新ができていません。更新を妨げている原因のひとつが、ホストに負荷をかけすぎないためにCPU負荷や自ユーザーのプロセス数をプロセスを起動せずにシステムコールだけで取得できるようにした自作のRubyライブラリでした。CGIから起動されるRubyスクリプトはまずこのライブラリを読んでシステムの負荷を測定し、問題がなければtDiaryの処理を始めます。これをなんとかモダンなエコシステムに乗せて更新を簡単にしたい。
というわけで、まずはsetup.rbではなくgemspecからビルドするようにしました。さて。次はCGIから起動されるスクリプトからこれを読めるようにになくちゃ。試行錯誤の結果、下記のようになりました。
Rubyの環境。このホストには、ruby 2.3.4p301が/usr/pkg/bin/ruby23としてインストールされています。これを使うようにします。
$ gem23 install bundle --user-install
PATHの最初に$HOME/.gem/ruby/2.3.0/binを追加しました。
Gemfile。ローカルな変更を使ってしまわないよう、GitHubにpushしたものを使うようにします。
gem 'netbsd_sysinfo', :github => 'zunda/netbsd_sysinfo'
このライブラリをローカルから参照できるようにします。
$ bundle install --path=vendor/bundle
CGIスクリプトは下記のような感じ。
#!/usr/pkg/bin/ruby23 require 'rubygems' require 'bundler/setup' require 'netbsd_sysinfo' puts "Load averages: #{NetbsdSysinfo.loadavg}" puts "Number of processes: #{NetbsdSysinfo.nprocs}"
これをローカルから実行すると、Content-typeレスポンスヘッダと共に端末に結果が表示されます。もうひといき。
Content-type: text/plain Load averages: [0.466796875, 0.37451171875, 0.34228515625] Number of processes: 2
さて。Apacheから実行しますよ。
.htaccess
Options +ExecCGI AddHandler cgi-script .rb DirectoryIndex index.rb
これがHTTP/1.1 500 Internal Server Errorになるんだな。CGIスクリプトを書き換えてエラーの内容を確認する。
#!/bin/sh echo Content-type: text/plain echo /usr/pkg/bin/ruby23 <<_END 2>&1 require 'rubygems' require 'bundler/setup' require 'netbsd_sysinfo' puts "Content-type: text/plain\n\n" puts "Load averages: #{NetbsdSysinfo.loadavg}" puts "Number of processes: #{NetbsdSysinfo.nprocs}" _END
RubyからのstderrもApacheに渡るようになります。
/usr/pkg/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': can from /usr/pkg/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in ` from -:2:in `<main>'
うーん。bundler/setupは~/.gem/ruby/2.3.0/gems/bundler-1.15.4/lib/以下にあるのです。下記ならApacheからでも実行できる。
#!/usr/pkg/bin/ruby23 $:.unshift("/home/zunda/.gem/ruby/2.3.0/gems/bundler-1.15.4/lib/") require 'rubygems' require 'bundler/setup' require 'netbsd_sysinfo' puts "Content-type: text/plain\n\n" puts "Load averages: #{NetbsdSysinfo.loadavg}" puts "Number of processes: #{NetbsdSysinfo.nprocs}"
どこかで誰かがこのパスを特別扱いしてるんだなあ…
最近のツッコまれどころ