
簡単なスクリプトがあります。
#!/usr/bin/env ruby --verbose
# script.rb
puts "hi"
私のOSXコンピュータではうまくいきます。
osx% ./script.rb
hi
しかし、私のLinuxコンピュータではエラーが発生します。
linux% ./script.rb
/usr/bin/env: ruby --verbose: No such file or directory
Shebangラインを手動で実行すると正常に動作します。
linux% /usr/bin/env ruby --verbose ./script.rb
hi
ruby --verbose
ただし、これを単一のパラメータに圧縮すると、エラーを複製できます。env
linux% /usr/bin/env "ruby --verbose" ./script.rb
/usr/bin/env: ruby --verbose: No such file or directory
env
したがって、Shebang Line Resetの問題をこのように説明しているようです。私はGNU coreutils 8.4を使用していますenv
。
linux% /usr/bin/env --version
env (GNU coreutils) 8.4
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Richard Mlynarik and David MacKenzie.
本当に変に見えますね。これがこのバージョンの一般的な問題ですかenv
、それとも私が認識していない他の問題はありますか?
答え1
これは、Linux(BSDとは異なり)がshebangコマンド(この場合はenv)に単一の引数だけを渡すためです。
答え2
Coreutils>=8.30:
#!/usr/bin/env -S ruby --verbose
-S
または、envオプションは--split-string
GNU coreutilsのマニュアルに記載されています(参照:info '(coreutils) env invocation'
またはオンラインマニュアル)。以下は抜粋です:
ほとんどのオペレーティングシステム(例:GNU / Linux、BSD)は、最初のスペースの後のすべてのテキストを単一の引数として扱います。したがって、スクリプトでenvを使用するときに複数のパラメータを指定することはできません。
次の例では:
#!/usr/bin/env perl -T -w print "hello\n";
オペレーティングシステムはこれを
perl -T -w
パラメータ(プログラム名)として扱い、次のようにスクリプトの実行が失敗します。/usr/bin/env: 'perl -T -w': No such file or directory
この
-S
オプションは、env
単一の文字列を複数の引数に分割するように指示します。次の例は期待どおりに機能します。$ cat hello.pl #!/usr/bin/env -S perl -T -w print "hello\n"; $ chmod a+x hello.pl $ ./hello.pl hello
perl -T -w hello.pl
コマンドラインプロンプトで実行するのと同じです。
答え3
@rampionコメントでこれを見つけました。
何が起こるかは、カーネルが#!を探すファイルの最初の2文字を処理することです。これらの文字が見つかったら、すべての空白文字をスキップし、空白以外の文字を探し、他のスクリプトではなく実際の実行可能ファイルでなければならないインタプリタパスを抽出します。ただし、Linuxは再帰スクリプトの処理を可能にするように拡張します。見つかったら、空白ではなく最初の文字にジャンプし、そこから次の改行文字にジャンプして単一の引数としてコマンドに渡します。引用符やその他のメタ文字の「シェリング」はありません。それはすべて非常にシンプルで暴力的です。だからあなたはそこのオプションに興味を持つことはできません。空白を含む引数を取得し、「perl -w」はカーネルがここで見て渡すことです。
源泉:http://lists.gnu.org/archive/html/bug-sh-utils/2002-04/msg00020.html