いまさら聞けない、#! で始まる1行目の名前とenv指定時の挙動
シェルスクリプトであれば1行目に #!/bin/sh と書くと思うのですが、1行目の名前や挙動についてよく分かってなかったので調べてみました。
名前
シバンまたはシェバン (shebang) とはUNIXのスクリプトの#!から始まる1行目のこと。起動してスクリプトを読み込むインタプリタを指定する。 hash-bangまたはsharp-bangとも言うが、後者を縮めたshebangという呼び方が一般的かつシンプルである。
シバンというのですね。
この「#!」のことを「シェバング」(shebang) と呼ぶ。また、この行全体を「シェバング行」と呼ぶこともある。シェバングの語源は「sharp bang」「shell bang」など、いくつかあるようだ。
なぜ、#! なのか
コンピュータが直接解釈できるのはマシン語だけである。しかし UNIX では、ファイルの先頭 2バイトが「#!」であった場合は、その後に記述されている別のコマンドを実行しようとする。
env を使う場合の挙動について
/usr/bin/env を使えばパスを直接指定する必要はなくなるが、インタプリタにコマンドライン引数としてオプションを渡すことができない。
「インタプリタにコマンドライン引数としてオプションを渡すことができない。」とはどういうことでしょうか。Rubyで実験してみます。
rubyでコマンドラインオプションを渡せない実験
'-v'' オプションを使って実験します。
envを使わない場合
% echo '#!/usr/local/bin/ruby -v' > hoge % chmod 755 hoge % ./hoge ruby 1.8.6 (2009-06-08 patchlevel 369) [i686-linux]
rubyでコマンドラインオプションを渡せない理由
[ruby-list:41934] Re: Cygwin での #!/bin/env ruby -Ks
多くのOSでは#!記法は引数を一つしか受け付けないので、オプションを付けて呼び出したい時にはenvは使えません。envを使うとrubyインタプリタをPATHから検索してくれるので便利なこともあるんですけどね。
おまけ:Mac OS X 10.6.2 でやったら env でも複数の引数が渡せた
envを使わない場合
% echo '#!/opt/local/bin/ruby -v' > hoge % chmod 755 hoge % ./hoge ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-darwin10]
おまけ:実験環境
OS | Mac OS X 10.6.2 |
おまけ2:不正なシバンが無視される場合
不正なシバンが無視される場合があります。
#!/opt/local/bin/rubyfoooooooooooo puts "test"
以下の結果を見ると、コマンドラインでインタプリタを指定するとシバンを無視するようです。
% ruby shebang_test.rb test % % ./shebang_test.rb zsh: ./shebang_test.rb: bad interpreter: /opt/local/bin/rubyfoooooooooooo: no such file or directory
しかし、以下の例は無視されません。
#!/opt/local/bin/hogefugabazfoooooooooo puts "test"
実行結果は「Can't exec」になります。シバンに ruby の文字が有るか無いかで判断しているようです。
% ruby shebang_test.rb shebang_test.rb:1: Can't exec /opt/local/bin/hogefugabazfoooooooooo (fatal)
この辺り、Twitterで少しやりとりがありました。
- shebangを書いてもコマンドライン側でインタプリタを指定していればshebangは無視される。 #lrtechtips
- と思ったけど、#!/opt/local/bin/hogefugabazfoooooooooo と書くと無視されない・・・むむむ
- でも、 #!/opt/local/bin/rubyfoooooooooooo だと無視される・・・前方一致とかやってるのかな・・・
- @japanrock "ruby"の有無だけ
- @japanrock ちなみに1.9だとshebangにrubyが含まれていない場合、-xが指定されているとみなします。つまり、/^#!.*ruby/までを無視。見つからなければエラー。
おまけ2:実験環境
OS | Mac OS X 10.6.2 |
まとめ
誤解している部分もあるかと思いますので、ツッコミお願いします><