(about 'mooz) ; => "See http://mooz.github.com/index-ja.html"
先日行われた Ruby 会議 2011 の LT で Rios という自作のモジュールについて発表する機会を頂きました.SlideShare に発表資料を上げましたので,以下に URL を載せておきます(何を血迷ったか自作の別ツールを宣伝してしまってスミマセン……).
この記事では LT 中に触れられなかった点について,簡単な補足などを行ないます.
Rios を一言で説明すると「CLI (Command Line Interface) のためのプロキシフレームワーク」となります.「プロキシフレームワーク」という言葉自体が私による全くの造語なため,イメージもわきにくいことでしょう.
「CLI」という言葉は,Rios の対象とするアプリケーションを意味します.こうしたアプリケーションでは,インタフェースが文字のみで構成されており,ユーザも文字を打ち込んで操作を行ないます.例としては bash や zsh などのシェルや,Emacs / Vim などのエディタなどがあげられます.
「プロキシ」という言葉はRios の挙動を表しています.Rios は以下の図に示すように,コマンドラインアプリケーションとユーザの間に入り込み,彼らの間で交わされる全ての文字的メッセージを仲介し,監視し,時には改変します.この動作はまさにプロキシ的です.
「フレームワーク」という言葉は,「Rios を用いることによって以下に示すような様々なアプリケーションを容易に構築することが出来る」という理由によりつけたものです.「ライブラリ」と呼んでも語弊はないでしょう.しかし「フレームワーク」の方が,響きが良い気がしています.
Rios の開発は GitHub で行なっています.何か面白いことを思いついた方はお気軽に pull/request を.
非常に雑駁となってしまいましたが,ここでは Rios の仕組みについて解説します.
Rios は基本的に script コマンドと同様のアイディアで動いています.具体的には fork()*1 を 2 回行ない,計 3 つのプロセスを立ち上げます.そして以下のような役割分担をして処理を行なっていきます.
| プロセス | 作成方法 | 役割 |
|---|---|---|
| 親プロセス | 元のプロセス | ユーザの入力をフックし,処理結果をプロキシ対象に渡す |
| 子プロセス | 親プロセスから fork() | プログラムからの出力をフックし,処理結果を端末に表示する |
| 孫プロセス | 子プロセスから fork() | プロキシ対象の起動(プログラムなら exec(),ブロックなら実行) |
簡略化したコードで示すと,以下のようになります(rios/lib/rios/proxy.rb).
fork { fork { do_command() } do_output() } do_input()
ここで,本家である script コマンドのやっていることを説明しておきましょう.script コマンドは do_output() 内で,端末への出力と同じ内容をファイルへ書き込んでいるのです.どうでしょうか.非常に単純です.
Rios では script コマンドにおける「端末への出力と同じ内容をファイルへ書き込む」という処理部分をユーザが Ruby で自由に記述できるようになっているため,さらなる応用が可能となっています*2.
さて,プロキシ対象のコマンドライン出力と入力はどのようにしてフックするのでしょうか.この部分を,簡単な手順として以下に書き下しました.
$stdin, $stdout, $stderr を全て tty (slave) に切り替える
リンク関係のある pty, tty のペアを利用して,うまく横流しをやっているというわけです.これに関しては他にも色々と特筆すべき点があるのですが,この辺りの説明は以下の良書に譲りたいと思います.
デーモン君のソース探検―BSDのソースコードを探る冒険者たちのための手引き書 (BSD magazine Books)
今回は Ruby 会議での発表ということや様々な事情があり,発表資料の作成には Rabbit を用いています.元々は使い慣れた PowerPoint で資料を作り,それを PDF 形式で保存したへ上で Rabbit により「ウサギと亀」を表示する予定でしたが,途中で Windows と Ubuntu を行き来することに嫌気が指したために,結局は RDoc 形式で作成を行なうことになりました.実際にスライドを作成してみるとレンダリングの綺麗さ,そしてテキストベースなスライド作成の行いやすさに感銘を受けてしまい,これからも Rabbit にはお世話になっていくだろうと感じているところです.
RDoc で作成した発表資料を PDF 形式に変換することも簡単にできるので,驚きました.以下のように -p オプションを渡した上で,出力先に拡張子が .pdf なファイルを指定するだけです.
rabbit ./slide.rd -p -o slide.pdf
CodeRay を使ってハイライトしたソースコードをスライドに含めると,そのスライドの表示が幾分もたつく点が気になったので,時間を見つけて Rabbit のソースコードも探検してみようと考えているところです.