Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

一発環境導入なワンライナー「ruby -e "$(curl ~)"」の挙動について調べてみた

homebrew公式では環境導入として次のようなスクリプトが紹介されています。

$ ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"

こういうの、たまに見かけますよね。
何となく意味はわかりますが、こういものをオマジナイとして思考停止すると碌な目にあいません。
というわけで、今回はこのワンライナーの挙動を調べてみました。

curl側の挙動

中で呼び出してるcurlの挙動です。
読み込みミスを防ぐために予防線張りまくってる感じですかね。

-f, --fail

HTTP サーバエラーが生じたときに黙って(何も出力しないまま)終わらせます。

-s, --silent

沈黙モードにします。

-S, --show-error

-s, --silent と伴用すると、失敗時にはエラーメッセージが表示されるようになります。

-L, --location

HTTP/HTTPS 要求したページが別の場所に移動していた場合に(サーバからの Location: ヘッダ行と 3XX 応答コードで検知されます)、このオプションにより,新しい場所に対して要求を再試行するようになります。

ruby側の挙動

さて、本題のRubyワンライナーの部分です。
「-e」オプションをつければ、引数にした文字列のスクリプトを実行してくれます。
コレ自体はよくあるワンライナーの話ですが……
問題は、これに「$(~)」とかいう明らかに見慣れない構文がついている点です。
ためしに括弧内に「ls」や「pwd」といったコマンドを打ってもエラーが返ってくるだけです。
指定先を見るとRubyスクリプトが書いてあります。

$はRubyの特殊変数なんかでよく使われる子です。
そういう情報はRubyリファレンスマニュアルが確実です。

探索の結果、該当しそうな記述をみつけました。

$FILENAME -> String
仮想ファイル Object::ARGF で現在読み込み中のファイル名です。 ARGF.class#filename と同じです。

この変数はグローバルスコープです。

Object::ARGF自体は

引数 (なければ標準入力) で構成される仮想ファイル

という扱いになっています。

まとめ

まとめますと......「ruby -e "$(curl ~)"」というワンライナー

  1. 読み込みエラー防止オプションをつけたcurlを実行
  2. 外部に用意したRubyスクリプトを標準出力に書き出す
  3. 標準出力に出て来たRubyスクリプトをブンまわす

という挙動をするようです。
つまり、上の例は

$ curl -fsSL https://raw.github.com/mxcl/homebrew/go) -o homebrew.rb

$ ruby ./homebrew.rb

と等価という事になります。