web-dev-qa-db-ja.com

Linuxで `#!/ usr / bin / env command --argument`を含むシバン行が失敗する

私は簡単なスクリプトを持っています:

#!/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 --verboseenvの単一の引数に

linux% /usr/bin/env "Ruby --verbose" ./script.rb
/usr/bin/env: Ruby --verbose: No such file or directory

したがって、これはenvがシバン行のリセットをどのように解釈するかに関する問題だと思います。 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の一般的な問題ですか、それとも、ここで何かわからないことはありますか?

56
rampion

これは、Linux(BSDとは異なり)がShebangコマンド(この場合はenv)に単一の引数しか渡さないためです。

これはStackOverflowで幅広く議論されています

48
rampion

@rampionコメント経由でこれを見つけました:

何が起きるかは、カーネルがファイルの最初の2文字を処理して#!を探すことです。それらが見つかると、スペース以外の文字を探すすべてのスペース文字をスキップし、インタープリターパスを抽出します。インタープリターパスは、実際の実行可能ファイルであり、別のスクリプトではない必要があります。それが見つかると、最初の非スペース文字にスキップして、そこから次の改行文字に移動し、それを単一の引数としてコマンドに渡します。引用符やその他のメタ文字の「シェル」処理はありません。それはすべて非常にシンプルでブルートフォースです。したがって、そこにあるオプションを気にする必要はありません。引数の空白が1つだけ含まれ、 'Perl -w'はカーネルがここで認識して渡すものです。

ソース: http://lists.gnu.org/archive/html/bug-sh-utils/2002-04/msg00020.html

5
Aalex Gabi