vagrant + chef-solo provisioningが初めて動くまで

あるいは Kanazawa.rb meetup #9 は「意識高いもくもく会」です。

はい、まぁ最近じゃ今さらの話ですね。

Chef って興味あったんですよというか正確には Puppet に興味があって、でも大げさだなと思ってたんですよね。あと当時は Puppet は外部DSLだったので、「Rubyの文法でもなんでもない設定って、どうやってエディタでハイライトするの?」というのが最大の心理的ハードルでした。

で、時は流れて Software Design の Chef 特集を読んでやる気になったけど、本家のリファレンスと格闘しているうちに仕組みの大掛かり感が増長されて挫折。その後ビッグウェーブに乗って達人出版会で買った『入門Chef Solo』を読み、そこでようやく

「サーバの状態を管理し収束させるためのフレームワーク」

という表現がグサッと刺さって、分かった気がしたのでもう一度やってみました。で、一応動くところまで来たので、今回改めて感じたことをまとめておこうと思います。

Vagrantのメリットよく分かってなかった

VirtualBox は以前から使っていたのでなんでわざわざ Vagrant なんか使うの?ってずっと思っていたんです。今も自分で使う分には Vagrant である必要はないよなーと思いつつ、以下のようなところがメリットかなと今は思っています。

  • 手作業での設定を必要としないので VirtualBox をよく分かっていない人にも同じように VM を配布することができる
  • ある程度設定の完了した VM を box として package して共有しやすい
    • 生の VirtualBox で VM の使い回しをやろうとするともっと手間が掛かる

※ vagrant 1.1 から単なる VirtualBox の wrapper ではなくなったのでそこにメリットがある人はぜひ使いましょう。

Vagrantの扱いにくさをよく分かってなかった

  • Vagrant は gem install もできるが基本的には配布パッケージが最新
  • 特に今(2013年初夏)は 1.0/1.1/1.2 の過渡期で設定ファイルのフォーマットが違ったりいろいろややこしい
    • Windows で動かすことを思うと1.2がよいが gem の最新は 1.0.x
    • でも Bundler で扱えた方が周辺ツールも含めて管理できるので本当はそっちがよい

org-binbab/gem-vagrant-wrapper · GitHub

という神 gem があります。これを入れると最新の package 版 Vagrant を使いつつ Bundler 管理できるようになって超絶便利。

Chef Solo + Knife Soloという構成はWindowsに厳しすぎる

Chef を使うにあたって『入門Chef Solo』を参考にしたので当然のように全体の作業は Knife Solo ベースでやっていました。

Knife は慣れてくると cookbook を作り実行するというサイクルの中心に置いたときにすごく使いやすいことが分かってきます。それは間違いないんですが、いかんせん

ssh + rsync で cookbook を転送する

というその仕組み上、Unix 系の開発者でない人が使っている(いわゆる普通の)Windows とは相性が悪すぎます。

結局WindowsではVagrant + chef-solo provisoningに落ち着いた

knife solo で cookbook を練っていって、最後は

config.vm.provision :chef_solo do
  ...
end

に反映されるようにしました。まだこの部分の Vagrantfile の生成やバージョンの管理方法はきれいにまとまってないのですが、方針としてはそういう形で行こうと思ってます。 Windows 用の手順をまとめると

  1. VirtualBox をインストール
  2. Vagrant をインストール
  3. vagrant plugin install vagrant-vbguest
  4. Putty + vagrant-multi-putty plugin の準備
  5. vagrant box add <BOX URI>
  6. vagrant up

といった感じ。実際には

  • Putty 周りの設定が慣れてない人はやや面倒(PATH が通ってなきゃいけない)
  • vagrant putty でなぜかパスワードを聞かれる(なんでかよく分かってない)
  • 例えば Rails の環境を作るためには vagrant putty したあとに bundle install とかお約束の作業は必要
    • そのうえで rails server 立ち上げるなども必要

てな感じで2回コマンド叩いたら何もかも完了、みたいなことは実現できないんですが、初回の待ち時間はともかく、サーバの設定が全自動で済んでいるというのはやはり大きいと思います。少なくともサーバ構築とかまったく目的ではない人にとっては書かれた通りに作業するだけでいいというのは魅力的なんじゃないかな。

VagrantのChef Solo Provisioningで思い込んでいたこと

Chef を実行するのは VM 上なんだからどうにかして VM 内に cookbook 運ばなきゃいけないですよね。で、VirtualBox の共有フォルダに置くとかしなきゃいけないのかなと思ったけど、そんな必要はありませんでした。なんか自動でうまいこといってた。

ChefのCookbookを育てる環境とそうでない環境

上の vagrant-wrapper 頼みで cookbook を育てる環境の Gemfile は以下のようにしました。

# -*- mode: ruby -*-

source 'https://rubygems.org'

gem 'rake'
gem 'vagrant-wrapper'
gem 'chef'
gem 'knife-solo', '> 0.2', :git => 'https://github.com/matschaffer/knife-solo.git', :tag => 'v0.3.0.pre3'
gem 'sahara', :git => 'https://github.com/ryuzee/sahara.git'
gem 'vagrant-vbguest'

これで git と gem と ssh の使える環境では knife solo でもりもり cookbook を作ったり実行したりできます。provisioning にしか興味のない環境では bundle install はしないで package の Vagrant を直接叩いて作業してもらいます。

Chefでようやくつかめてきたこと

すべてはリソースと見つけたり

Chef って語る要素がすごく多いんですが、要は

  • ホストの状態を収束させる
  • そのためにリソースをキーにしてコードブロックを与える
    • その中で only_if, not_if でちゃんと状態をチェックする
    • 楽して execute リソースを選ぶと実行の終了をきちんと待てずに2回実行しないと安定しないといったことも起きるので注意

の大きく2点が大事かなということに気づき始めました。

正直言うと sh script の方が楽じゃないのと思うポイントはまだ多いし、生のコマンドでできることが chef の resource に落とし込んだ段階で制限されて変に手間の多い recipe になるといったことはあります。でもやはりそこは手間と思っても分けておいた方が段階的に実行する/しないをチェックでき、最終的には早く収束される方向に振ってあって、試してるうちにうまいなぁと思うようになってきます。

  • 特に条件分岐を sh script で書き始めるとコードがすぐややこしくなる
  • なにより sh script では再利用しにくい
    • Chefでちゃんとリソースを意識してrecipeを書いていればrecipe単位, cookbook単位での再利用しやすさがある程度自然と確保される

辺りが感心するポイントでした。

recipeの分け方

今のところ以下のような方針でやってます。

  • とりあえず 1アプリ:1 cookbook
  • cookbook には default recipe があるんだけど、とりあえず cookbook と同名の recipe を作って明示的に呼ぶようにしてる
  • 特に何らかの設定が必要だったり事前準備の必要なアプリのインストールの場合はこの分け方がいい
  • 設定が不要でただインストールすればいいものはいくつもまとめてしまっちゃってok
  • cookbook が分かれていなくても recipe が分かれていれば include_recipe で再利用できるので、分けて再利用する

recipe の再利用は

include_recipe "#{cookbook}::#{recipe}"

で記述するんですが、recipe 内では #{cookbook_name} で自身の cookbook の名前を知ることができる1ので、同じ cookbook 内の recipe も違う cookbook 内の recipe も自在に再利用できます。

再利用を前提にあれこれやっているうちに

  • とりあえず何をするときにどこを見ればいいか
  • 何が分かっていないか

がだんだん分かってきたので、以前よりはだいぶ recipe を書くのは早くなってきました。

次の課題

例えば複数の Rails 環境を用意したい場合、『入門Chef Solo』方式で hostonly で IP アドレスを固定していくのがいいのかどうか、迷っています。Vagrantfile を組み立てる rake タスクを用意して2、用途に応じて Vagrantfile を生成したのち vagtant up するのが手間も少ないし、見通しもいいのかなぁという感じのことを考えています。

でもそのうちまた違うこと言ってるかもしれないです。

chef というか vagrant を使ったホスト管理の話ですね、これは。

  1. Ruby 的には instance variable に attr が設定されているだけ 

  2. 一応 Vagrant を入れた環境には必ず Ruby も Rake もあるので 

capybara-mechanizeでSJISのページを扱う

[20130729 追記]

Ruby 1.8 前提の書き方になっていたのと、Ruby 1.9 以降を使っている場合に Capybara-mechanize 1.0 前後で挙動が変わる記述を追加。

scrapeはmechanizeらしくUTF-8のままでok

click_on( '次へ>>' )

みたいな記述は UTF-8 で書いたものがそのまま動く。

テスト時はUTF-8への変換が必要

Ruby 1.8 では

body.toutf8

でよかった。

it {
  body.toutf8.should include('ほげげげ')
}

みたいな感じ。

kconv を require した覚えがないのに kconv が動いてるのはなんでだろう。

まーいっか。

もし&#xxx;形式になってたら

(Ruby 1.8で動かしている場合は $KCODE = 'u' したうえで)

CGI.unescapeHTML(body)

でいいみたい。

ちなみにSelenium WebDriverの場合

全部 UTF-8 で扱える。Selenium で書いていって Mechanize で CI に乗せる、といった運用を考えている場合はここが食い違うので注意が必要。

Ruby 1.9+ の場合

いずれも Mechanize 2.7.1 で試した。

HTTP Response Header に charset がない場合の挙動が Capybara 1 と 2 の間、あるいは Capybara-mechanize 0.x と 1.x の間で異なっているので注意が必要。

たぶんイマドキは charset UTF-8 に統一してあれば response header に入ってそうな気はするけど、古い日本のサイトだとダメな気がする。

'capybara-mechanize', '< 1.0'

自動で正しく encoding を判別できていたので

.encode('UTF-8')

で OK

'capybara-mechanize', '> 1.0'

HTML の中に charset 指定があってもダメで HTTP Response の charset だけをアテにして encoding の判別に失敗するようになってしまい Encoding::UndefinedConversionError: … from ASCII-8BIT to UTF-8 エラーが出る。

仕方ないので

.toutf8.force_encoding('UTF-8')

を挟んだらうまくいった。

bind を上げてちょっとハマって反省した

bind 9.4 以降の allow-* の設定

Debian を etch から lenny に上げた関係で bind のバージョンが上がった1。そしたら別セグメントのネットワークから forward 先の DNS を引けなくてちょっとハマったので覚え書き。

acl "allowed-hosts" {
  .. ;
  .. ;
};

options {
  allow-recursion { "allowed-hosts"; };   // <- added
  allow-query-cache { "allowed-hosts"; }; // <- added
};

こんな感じみたい。

default が localhost.localdomain なのでこの設定を明示しておかないと別セグメントのネットワークからは DNS が引けないとか forward されないといった問題が起きる。2

allow-recursion, allow-query, allow-query-cache 辺りは互いに補完するような関係らしく、ややこしいのであまり突っ込む気なし。

今回のケースはサーバのそばにいる自分の環境からは検証できない現象なので、気づくまで時間が掛かってしまった。うーん反省反省。

bind-announce のチェック

※ ここから先は実は5月26日の話

bind のアップグレードはいつも気を使うんだけど、日常的にはちゃんと情報を追いかけてなくて、たいていちょっとトラブる。(そんな長い時間じゃないんだけど。)

なんで bind の情報に追いついていないのかなと思ったら案の定 feed を購読していないから。そもそも bind は本家がどこかもよく分かっていないような状態で、そらいかんわなと反省。

で、feed を探すが見つからず。こういう古いアプリはサイトの作りも情報の告知方法も古いのが世の常。bind-announce という ML があるのは分かったが ML にはもう入りたくない。

そこで Nabble という ML アーカイブサービスを思い出した。これは ML のアーカイブを独自に作れて、かつそれを rss にも変換してくれるサービスなのだ。sign up して…えーとオレが思い描いているのとすでに画面が違うっ。使ってないのバレバレ。

あれこれ試行錯誤したが違うサービス上ですでに bind-announce の feed が配信されているのを発見。あーじゃあこれでいいじゃん。

Gmane – Mail To News And Back Again

ということで FLDR で subscribe 完了。よしよし。

cf.

  1. 9.3.4 -> 9.5.1 

  2. 本当は DNS 管理者は早い段階でこの辺の設定について分かっているべき。自分があまり神経質になっていないのは内向けの運用だからなの、と言い訳しておく。 

Trac に PeerReviewPlugin を入れてみた

先日、ようやくアジャイルプラクティス読了

コミットされる前のコードをどうやってレビューするの?という初歩的な話。だってコミットされていないコードは基本的に開発者のローカルの環境にあるわけでしょ?

と書いていたけど、そう言えば reviewboard なんてものがあったなぁと思い出して動かすことを試みた。しかし

monospace blog オンラインソースコードレビューツールのReviewBoardをインストールしてみた

にしたがって Debian etch で作業してみたがあえなく失敗。(Python Image Library が入らなかった。Django も経験ないし。)

気分を替えて Trac に PeerReviewPlugin - Trac Hacks - Plugins Macros etc. - Trac をインストール。こっちは Trac の plugin 特有のクセを把握できてなくてちょっと手間取ったけどなんとか動いた。

※ Trac 0.10.4 with Apache 2.2 + mod_fastcgi on FreeBSD 6.3R と Trac 0.10.3 with Debian etch + Apache 2.2 + mod_python 3.2.10 で確認。

やったことは以下の通り。

  1. PeerReviewPlugin を Python モジュールとしてインストール
  2. Webサーバの方へ EGG 周りの設定を追加
  3. trac.ini で Trac インスタンスについて有効に
  4. trac-admin で権限を付与
  5. trac-admin PATH upgrade

plugin を Python モジュールとしてインストール

TracPlugins The Trac Project Trac のまま。

  • setuptools( easy_install ) をインストール
  • easy_install で PeerReviewPlugin をインストール(EGG として Python の site-packages に入る)

Trac のバージョンによって対応するものが違うのでそれに合わせてインストールすること。easy_install に慣れていなかったのでどこで何を指定して easy_install を起動すればいいのか分からなかったけど、エラーメッセージや back trace を読みながらよちよち作業を進めたらなんとかなった。こういうとき Python や Ruby で書かれたツールは助かる。

しかしあとになって実は下の Google Group のリンクをたどれば何をすればいいかが分かった。今回インストールしたのは 0.10 用のものなので

sudo easy_install http://trac-hacks.org/svn/peerreviewplugin/0.10

でよかった1

WebサーバにEGG用の設定を追加

以前 WebAdminPlugin を入れたときにももしかしたらやってたのかもしれないけど、あれは別な環境でやっていたのですっかり忘れていた。EGG は cache を指定しなければいけないらしく、FastCGI で動いているうちの環境では

 FastCgiConfig -initial-env TRAC_ENV=/var/lib/trac
+              -initial-env PYTHON_EGG_CACHE=/var/lib/trac/plugin-cache

を書き足した2。(パスはサンプルに載っているまんまなので適宜書き換えること。)

使いたい Trac インスタンスについて有効に

この部分の記述が全然不十分で手間取った。

trac.ini の中で

cannot install peerreview (not picked up) - trac-peerreview-dev | Google グループ

に従って

[components]
codereview.* = enabled

で plugin を有効にする。また

/peerreviewplugin/trunk/README.txt - Trac Hacks - Plugins Macros etc. - Trac

に従って

[trac]
mainnav = ..,peerReviewMain,..

を編集してメニューに組み込む3

権限の付与

trac-admin PATH permission list

とすると

  • CODE_REVIEW_DEV
  • CODE_REVIEW_MGR

が追加されているのでこの割り当てを行う4

使用感

ほんとに試しただけだけど、

  1. Trac の plugin なので当然 review 対象は reviewboard とは違って5 repository に commit 済みのコードの一部
  2. review の作成は 3 step か 4 step で、Ajax を使っていて難しいところはほぼない

という感じ。1 は運用ルールによっては問題になるけど、現状自分が関わっている部分では大丈夫かなと。

とりあえず Django のセットアップとか慣れないことをやらずに記録の残るレビューができそうなのはよさげだなと思っているところ。メール飛ばしたりなんだり、本格的には使っていないのでその辺は分かりません。

え? Retrospectiva はどうしたのかって? どうしましょうね。こうして plugin を使い始めると移行するのは難しいよねぇ。でもやっぱこういうプラグインのセットアップも Trac インスタンスごとにやらなきゃいけないのはイヤなんだよな。

[2008-06-02 追記] Review の様子が timeline に出ないぞ? timeline に出なかったら Review の追加はどうやって知るのだ? メールとか飛ばす設定があるのか? うーん、そりゃあどうだ。不便じゃないか?

Ticket みたいに Search の結果の feed を吐けるのかな、と思ったけどそんなこともない。というか自分宛に依頼のあった Review という条件では検索はできない。(まぁ My Code Reviews で出てはくるんだけど。)なんだかな。なんだかなぁ? 0.10 だからかい?

[2008-06-04 追記] あれ? Wiki の [source: link] 形式の記述が Source Browser じゃなくて peerReviewBrowser への link になって怒られるぞ? えーー。なんだよー。ダメじゃんよー。何乗っ取ってんだよー。

  1. svn co も自動でやってくれるなんてすごい変態的なツールに見えるけど、こんなもんなの? 

  2. mod_python の場合は SetEnv PYTHON_EGG_CACHE /var/lib/trac/plugin-cache になる。 

  3. 長い…。どうしたらいいんだ。 

  4. REVIEW を見るだけって権限がないんだよなぁ。 

  5. reviewboard の場合は repository とは別に patch を up して review 開始って感じらしい。 

乳剤なくなったらほんとにアウトだもんな

キヤノンも銀塩カメラ開発停止か? (/.-j)

35mm については銀塩はあんまり期待してないんですよ。現役で銀塩写真撮ってた時期からいずれ消えるなとは思ってたんで。ただフィルムや印画紙といった乳剤そのものの供給がかなり厳しくなってるんで、そのうち「カメラをはじめ機材は手に入るけど何もできない」という状況になっちゃうんだよな。カメラは中古でどうにでもなるけど、乳剤は生ものだから中古ってあり得ないし。そのうち「ビンテージ乳剤を使った半世紀ぶりの銀塩写真」とかいうよく分からない作品とか出てくるのかな? やだなぁ。困ったなぁ。

おれデジタルで写真楽しめるかなぁ? 不安だ。モノクロ派としてはやっぱ乳剤の力は圧倒的だもの。

※ このあと私はデジカメとろいし電池食うし値段の割にたいした描写力ねーしうざいんだよな、と暴言を吐いたのだった。駆逐するなら凌駕してくれ、頼む。

for あれこれ

for .. inの不思議

JavaScript の for ( i in array ) は i が添字だと。うーん、ちょっと書き出してみよう。

言語書き方i にくる値
JavaScriptfor ( i in array )添字
awkfor ( i in array )添字
shfor i in array っちゅーか list?要素
Rubyfor i in array要素
Perlforeach $i ( @array )要素
PHPforeach( $array as $key => $value )添字も要素もどっちも

Ruby は for も each も書き方が違うだけっぽいですが、for は awk 方式、each が shell 方式でもよかったかなとか勝手なことを思ったりした。

PHP 4 以降の foreach は要素を取り出すのと添字と要素の組み合わせを取り出すのと、両方の書き方

foreach(array_expression as $value) 文
foreach(array_expression as $key => $value) 文

が可能なんだけど、これ結構邪魔くさい。foreach ってのが長いくせに as とか => とか妙にタイプ量を上げるトラップが仕組まれてる。まぁ PHP 3 で使っていた

while ( list( $key, $value ) = each( $array ) )

よりはマシなんだけど。

mod_perl2 リリースと Apache2 への移行

mod_perl2 が出たらしい。(リンク先は /. なんだけど、オリジナルのリリース文書はないのかな?)

tdiary.net の稼働環境を見ると mod_ruby も Apache2 との間で深刻な問題はないだろうと判断できるので、あとは PHP かな? PHP5 への移行を伴わずに Apache2 で安定動作するようならそろそろ Apache2 にいっちゃってもいいかなぁ。(文字コードとか PHP の動作で悩んだのは2年も前の話か。)

Ming

高林さんは賢いねぇ。

ため息出ちゃうよ。

とりあえず MoBo から mingplot を使えたりするのが目標かな。ついでに PHP でも利用できるようになっちゃおう。

当面の目標

  • Pear をあれこれ
  • Ming でグラフとか

rsync cygwin ⇔ Linux

以前は Linux → cygwin(Linux 側で rsync を起動)の方が安定していると思っていたんだけど、今やってみると cygwin → Linux(cygwin 側で起動)の方が安定しているみたい。なんでだ?

cygwin 1.5.9rsync 2.6.0
Debian 3.0rsync 2.5.6

でもやっぱ実行途中で break すると shell ごとおかしくなるのは一緒なのね。

ck - terminal emulator

上の話で 2ch にダイブしてて見つけた。ちょっと使ってみよう。

……。cat は日本語が出るが less や lv では化ける。Emacs では ok. なんか設定が足りない感じ。rxvt-j のように行間を確保してくれないので詰まりまくり。情報量は増えるがちょっときついかなぁ。行間設定できるようになったりするとすげー嬉しいが。。。

地味に期待。

※ その後掲示板で確認したところ、jis を表示できないためと判明。jless は基本的に jis 系のコードしか出力できないので、このままでは使えない。lv の場合は出力オプションを指定してビュワーとして起動すれば問題ないことを確認した。

※ jless の設定で euc-jp を吐くようにしても対処可能。

FDclone on cygwin

FDclone はとにかくインストール手順がかったるい。./configure 使えないし、machine.h とか config.h 読めとか言うし。まぁメジャーなフリー OS の場合は何も考えずに make; make install で ok なんだけど、それがドキュメントのあとの方に書いてあったりするのがまたどうも。

2.04c で Cygwin に対応したというので make してみたが select(): Bad file descriptor でうんともすんとも。期待したらいかんか。

AVG 6 Free Edition のアップデート

from http://pc5.2ch.net/test/read.cgi/sec/1081426213/4

保全コピペ

Q.updateフォルダにあるファイル消していい?
A.avg6info.ctfと最新のアップデータ以外は削除してもok

Q.自動アップデートできない(繋がらない、重いetc)
A.後日行うか、手動アップデート

Q.手動アップデートの仕方は?
A.ttp://www.grisoft.com/us/us_updt6.php?avg6=fe
 上のサイトからAVG Free Edition Update Fileを落として
 Program Files/grisoft/AVG6/UPDATEに置いて
 タスクトレイからRun AVG Anti Virusか、スタートメニュー、プログラムからAVG 6.0 for Windows

 自動でアップデートが開始されない場合は、メニューのService→Update→Form a folder

Q.駆除できないんだけど?
A.隔離は出来るが、駆除は出来ない
 無償ウイルス駆除ツールは、コチラ↓
 Symantec
 ttp://www.symantec.com/region/jp/sarcj/tools.list.html
 Trendmicro
 ttp://www.trendmicro.com/jp/security/tool/overview.htm
 Grisoft
 ttp://www.grisoft.com/us/us_ts_removers.php

基本的には AVG の update フォルダ内に *.bin ファイルを突っ込んで Control Center とか立ち上げると自動的に内容を読み取ってアップデートを始めてくれる。

現時点(2004-05)で、AVG 6 は2回大きなアップデートが加わっている。差し当たり

http://free.grisoft.cz/softw/60/fe/ から

  • d6032lhj.bin
  • u61540k0.bin

を落としておいて、アップデートするとよい。ナローバンド環境でインストール際に使える。……と思ったらアップデート済みのバイナリがここにあんじゃん。がーん。

url.ini を書き換えればローカルに update 用のサーバを用意するのも不可能じゃないな。

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm