shlauncher で自作スクリプトの管理を簡単に(できるかも)

wtnabe's shlauncher at master - GitHub

こんなものを作ってみました。基本的には単純なもので

  1. rake を使って
  2. script/ 以下のスクリプトをリストアップして
  3. 目的のスクリプトを実行
  4. script/ 以下を含めたセットに名前を付けて gem 化できる

ものです。

もし似たようなコンセプトの似たツールが既にあったらニヤニヤしてください。

[2009-10-04 追記]gem化以外には rake を使わなくなりました。rake を使っていたバージョンはややこしい事情により OSX + zsh という非常に狭い環境でしか動きませんでしたが、ruby スクリプト化したことで Ruby の入っている Un*x 系プラットフォームならまずどこでも動くようになったと思います。

sh script が散乱してなんだか分からない

そもそも sh script を呼び出して実行するだけのことをなぜわざわざ rake にやらせようと思ったかと言いますと、

どんなスクリプトをそのシステム用に用意したか覚えていない

ということが発端だったりします。

最近は rake が好きなので割と何でもかんでも rake を使って作ることが多いのですが、以前作ったものは sh script やフツーの ruby script が圧倒的に多いです。でもこの形で作業用のスクリプトを増やすと、どういう作業にどういう名前のスクリプトを用意したのか忘れちゃって、「はて、このシステムでこれこれの作業をやるには何をどうすればいいんだっけ?」となってしまうことが増えてきました。1

まぁドキュメントを整理してあればある程度はなんとかなるんですけど、ドキュメントは書くのも探すのもコストだし、いろいろ面倒くさくなって似たようなものをもう一度作った方がはえー、なんてこともあるわけです。

これはいけない。

そこでできるだけドキュメントを書かなくても何ができるのか分かるようにする方法を考えました。思いついたのが「rake に task として登録してあれば、たった一つのアプリの起動だけ覚えておけば、何ができるか一覧にできるじゃないか」ということです。

本来は rake は -T を付けないとタスク一覧は出してくれませんが、一覧を出す task を default で定義しておけばいいだけです。

システム固有のスクリプトの置き場所とバージョン管理問題

もう一つ、これも以前から悩んでいたのが、

そのシステム固有のスクリプトの置き場所とバージョン管理システムの相性

です。

伝統的にはこれらは

/usr/local/bin
/usr/local/sbin

などに収まるものだと思います。置くのはいいんです。でもそのまま直置きしてしまうと「バージョン管理しにくい」です。さすがにこれらのディレクトリを丸ごと working copy にしてしまうのはなんか変だなと思いますし、じゃあどっか別な場所に置いて make install とか毎回やるの? 2

そこでいま採用しているのは「スクリプト実行用のユーザーを一人用意して、そこにスクリプトを展開してしまう」方法です3。この方法は複数あるスクリプトを一気に deploy するのが楽になります。しかし同時にこれらのスクリプトは system wide な PATH 上には置かれていないので、実行するユーザーが増減すると面倒なことになります。要するに覚えていないと呼び出せないスクリプトの、さらに置き場所まで分かっていないといけない、という高コストな方法なのです。

そこで rake task を gem 化できればインストールしやすく、かつスクリプトの修正はどのユーザーでも行うことができる状態になるんじゃないかと思ったわけです。

プラットフォーム固有のパッケージシステムの問題

パッケージングだけの問題であれば rubygems を採用する必要はありません。プラットフォーム固有のパッケージシステムを使えば済むからです。rpm, deb, ports, … 様々なパッケージシステムが各プラットフォームにあります。

逆に問題は各プラットフォームにパッケージシステムがあることです。プラットフォームが複数にまたがった瞬間、煩雑さがどんどん増していきます。実際いま運用しているシステムは複数のプラットフォームにまたがっていますので、プラットフォーム固有のパッケージシステムの採用は避けたいところです。

全部解決できそうな rake + rubygems 方式

そこで出た結論が rake + rubygems 方式です。

  • rake で散乱する script をまとめ
  • gem でインストールしやすくする

で、これらを適当なバージョン管理システムに突っ込んでしまえばよいわけです。

しかも gem 化するにはバージョン番号を決める必要がありますので4、ちゃんと最新の状態になっているかどうかの確認もしやすくなるはずです。

おまけ

今回のツールは script/ 以下のスクリプトを task としてリストアップして実行する機能を持っていますが、おまけとして script/ 内にディレクトリを掘っている場合、ディレクトリ名を task として指定するとその中のスクリプトを全部順番に実行するという機能を用意してあります。

これは以前

などで触れた、複数のスクリプトをまとめて実行する機能を独自に実装したものです。中を読めばビックリするほど簡単で実装なんて呼ぶのもおこがましい状態ですが、これが run-parts や periodic を使わずにできるようになったことも個人的には大きな収穫です。

仕様と既知の問題

  1. rake task としてリストアップするために、スクリプト内には必ず何らかのコメントが必要
  2. 引数を取る sh script は今のところ登録できない

1 は仕様です。最低限のコメントをすぐに閲覧できるように強制することで、運用の際に迷うことがないようにした方がよいという判断です。

2 はちょっと解決の方法を思いつきません。rake task は引数を取ることができるし、sh script に引数を渡すことも可能だと思いますが、任意の数の引数を自由にやり取りする方法が分からないのです。お手紙待ってます。

[2009-10-04 追記]task の実行の際に rake の利用をやめたので引数はほぼ自在に渡せます。

cutagem(と、あといろんなもの)に感謝

最後に、cutagem の作者、cho45 氏、genki 氏に感謝します。cutagem がなければ gem 化しちゃえばいいじゃんなんて、今の自分が軽々しく発言することはなかったと思います。それくらい cutagem は簡単に使え、十分に自分の目的を満たしてくれます。rubygems の作り方を自分が初めて delicious にブックマークしたのはもう2年以上前の話です。そこからたいした理由もないままウダウダと実際にやってみることを避けてきたボンクラな自分でも、「cutagem なら簡単だ!」と思わせてくれました。本当にありがとうございます。

関連つぶやき

twitter落ち穂拾い。基本的には mirroring で再現しにくいサーバを手早く起こすことを目的に語っています。ほとんど同じ仕事をするサーバを増やす(スケールアウト)ためのセットアップの簡略化は Web 上でよく見かけますが、そういう要求ばかりじゃないんだよーということが言いたいようです。

PHP をどうしても dis っちゃうのはクセみたいなもんですね。脱線するからよくないんだけど、マルチプラットフォームのパッケージシステムの例として出すのは一応間違ってないと思っています。

  1. トシのせいだけではありませんよ? :-) 

  2. あれ?前に Capistrano 持ち上げてなかった?と思い出した人はいい記憶力をしていますが、その話はとりあえず置いといてください。 

  3. よく考えると ~/bin に全部突っ込んでいるのと大差ないです。 

  4. ありますよね? 

More