おまぬけ活動日誌

最近のツッコまれどころ

この日誌から Google してもらう


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}"

どこかで誰かがこのパスを特別扱いしてるんだなあ…


作り手とその取り巻きだけが楽しんでる間は本物じゃない。その中身が理解できない人々の生活を変えてこそ本物だ


zunda <zunda at freeshell.org>