Edited at

Perl, Python 及び Ruby スクリプトにおける正しいshebangの書き方

More than 1 year has passed since last update.

Unix系OSでは、スクリプトの#!から始まる一行目(shebangと呼ばれる)によって、起動するインタプリタを指定することができる。以下はWikipediaから拝借した例である。


example1.sh

#! /bin/sh

echo 'Hello world!'

このshebangにはOSによって制約があったり解釈がまちまちであったりといろいろと厄介なことが起こる。

それはさておき、Rubyを起動するには、


example1.rb

#! /usr/bin/ruby

puts 'Hello world!'

のように書かれるが、Rubyが/usr/bin/rubyにあるとは限らない。システムによってはひょっとすると/usr/local/bin/rubyにあるかもしれない。この問題を避けるために、しばしばenvコマンドが使われる。


example2.rb

#! /usr/bin/env ruby

puts 'Hello world!'

これは大多数の環境で上手く動くと思われるが、しかし世の中には/usr/bin/envが存在しないようなOSが存在する。(卜部昌平のあまりreblogしないtumblr : #!/usr/bin/env)

結論として、こんな風に書くと良いらしい。(Ruby 1.8.7 リファレンスマニュアル : Rubyの起動 )


example3.rb

#! /bin/sh

exec ruby -S -x "$0" "$@"
#! ruby

起動されたshは2行目のexecでRubyに飛び、Rubyは3行目までを読み飛ばすという寸法である。

同じことをPythonでは以下のようにする。(effbot.org : How do I make a Python script executable on Unix?)


example.py

#! /bin/sh

""":"
exec python "$0" ${1+"$@"}
"""

__doc__ = """The above defines the script's __doc__ string. You can fix it by like this."""


一方、Perl使いはこうした。(The Magic Perl Header)


example.pl

#! /bin/sh

eval '(exit $?0)' && eval 'PERL_BADLANG=x;PATH="$PATH:.";export PERL_BADLANG\
;exec perl -x -S -- "$0" ${1+"$@"};#
'if 0;eval 'setenv PERL_BADLANG x\
;setenv PATH "$PATH":.;exec perl -x -S -- "$0" $argv:q;#
'.q
#!perl -w
+push@INC,'.';$0=~/(.*)/s;do(index($1,"/")<0?"./$1":$1);die$@if$@__END__+if 0
;#Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header

追記 (2015/10/21)

上記のPythonの例はpep257に引っかかるようだ。なので、このチェックをすり抜けるようにしてみた。


example2.py

#!/bin/sh

""":" .

exec python "$0" "$@"
"""

__doc__ = """
The above defines the script's __doc__ string. You can fix it by like this."""