26

以下のような単純な perl スクリプトがあります。

#!/usr/bin/perl

use strict;
use warnings;

print "hello world!\n";

このスクリプトを次のように実行できます。

>temp.pl
hello world!
>

次のようなコメントを追加すると:

#this script is just for test
#the shebang
#!/usr/bin/perl

use strict;
use warnings;

print "hello world!\n";

実行しようとすると、次のような出力が得られます。

> temp.pl
use: Command not found.
use: Command not found.
print: Command not found.
> 

ここでのポイントは、何があっても、シバン ラインは常に一番上にある必要があるということです。誰でも理由を説明できますか?

4

4 に答える 4

39

シバンは、実行可能ファイルの先頭にある 2 バイトを調べるカーネルによって解釈されるため、最初の行である必要があります。これら#!の行の残りの部分は、実行する実行可能ファイルとして解釈され、そのプログラムで使用できるスクリプト ファイルが含まれます。(細部は少し異なりますが、それは写真です)。

カーネルは最初の 2 文字だけを見て、それ以上の行を認識しないため、ハッシュ bang を 1 行目に配置する必要があります。

カーネルが で始まるファイルを実行できない場合はどうなります#!whateverか? シェルは、実行可能ファイルをフォークしようとし、プログラムを実行できないことをカーネルから通知されます。最後の手段として、ファイルの内容をシェル スクリプトとして解釈しようとします。シェルは perl ではないため、実行しようとした場合とまったく同じように、一連のエラーが発生します。

 sh temp.pl
于 2012-10-16T09:32:32.903 に答える
8

ここここここで詳しく説明されている上記の説明に加えて、#!と Perl についてまだ言及されていない特別なことがあります。

Perl#!は行を読み取り、2 つのことを行います。まず、パスが perl のように見えない場合、それを使用してプログラムを再実行します! 例えば...

#!/bin/sh

echo "Hello world!"

として実行すると正しく実行されperl /path/to/that/programます。Perl がこれを行う歴史的な理由はわかりませんが、Test::Harness で複数の言語をテストする場合に便利です。

2 つ目は、Perl が行内の任意のスイッチを見つけ#!て、コマンド ライン上にあるかのように適用することです。これが#!/usr/bin/perl -w、警告をオンにするように機能する理由です。

シバン処理の他の部分とは異なり、これはすべて Unix ではなく Perl 内で行われるため、Windows に移植可能です。

もう 1 つの Perl + shebang ノートは、多くの Perl プログラムの上部に見られるこの狂気です。

#!/usr/bin/perl

eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
    if 0; # not running under some shell

非常に非常に古いシステムで#!は、Perl プログラムがシェルによって実行され、動作しないことがあります。これevalにより、シェルは最初に Perl でファイルを再実行するように強制されます。シェルステートメントは改行で終わるため、if 0. Perl は を認識しているif 0ため、eval を実行しません。evalPerl とシェルの両方に、ハックを機能させる構文的に同等の演算子があります。

于 2012-10-16T09:52:47.270 に答える
8

最初の行でなければならないだけでなく、文字#!はファイルの最初の 2 バイトでなければなりません。これがスクリプトを実行できることは、OS の機能ではなくシェルの機能であり、特定のスクリプト言語に固有のものではありません。

システムがファイルの内容を実行するように指示されると、 のようなものを使用するか.../path/to/bin/program、PATH を介した類似のルートを介して、ファイルの最初の数バイトを調べて、ファイルの種類を明らかにする「マジック ナンバー」を探します。そうです (file(1) コマンドを使用して、そのプロセスを覗くことができます)。コンパイルされたバイナリの場合は、適切な方法でロードして実行し、最初の 2 バイトが#!そうである場合は、「シバン ハック」を実行します。

「シバンハック」は、シェルが改行までの残りのバイトを読み取り、これらをファイル名として解釈する、一部のシェルで採用されている特別なケースです (実際には、基本的にすべてのシェルですが、要件ではなく規則です)。 、そしてそのファイルを実行し、現在のファイルの残りを入力として与えます。さらに、おそらく他の場所で読むことができるいくつかの詳細。

一部の(バージョンの) シェルでは、非常に長い最初の行が許可されますが、一部のシェルでは短い行しか許可されません。複数の引数を許可するものもあれば、1 つだけを許可するものもあります。

ファイルが で始まらないが#!、テキストのように見える場合、一部のシェルはヒューリスティックにそれを実行しようとします。Csh (私の記憶が正しければ) は、csh スクリプトであることにパントを使用します。また、最初の行が空白の場合、いくつかのシェルの動作に関係する複雑で不可解なケースがあり、その寿命が短すぎて覚えられません。

Sven Mascheckの #! ページ

于 2012-10-16T09:31:08.383 に答える
0

少なくともPOSIX準拠のシステムでは、実行可能ビットが設定されているテキストファイルをどう処理するかを実行可能ローダーに指示するためにシバンが使用されます。

ローダーはバイナリファイルをどう処理するかを知っています。バイナリファイルは「マジックナンバー」で始まり、通常は最近ELFに関連しています。

一方、シバンがないテキストファイルは、マシンで使用可能なPOSIX準拠のシェルによって実行されます。これが、次のシェルエラーメッセージが表示される理由です。

use: Command not found.
use: Command not found.
print: Command not found.

実行可能ファイルがPOSIX準拠のシェルによって解釈されない場合は、使用するインタープリターをローダーに指示する必要があります。Windowsのような他のOSはそれを理解するためにファイル拡張子を選びますが、Unixはこの特定の場合に拡張子を使用したり気にしたりしません。使用するのは、使用するコマンドインタープリターを示す最初の行のシバンです。唯一の欠点は、スクリプト言語がこの最初の行を無視する必要があることです。これは#、ほとんどのスクリプト言語のコメント行プレフィックスと同様に、うまくいけば当てはまります。

一般に信じられていることですが、ポータブルスクリプトにはシバンを含めるべきではありません。特に#!/bin/sh彼らにはお勧めできません。

于 2012-10-16T10:44:20.843 に答える