シェルスクリプトは#!なしでも動作します(sha-bang行)


10

私はシェルスクリプトに慣れていないため、スクリプトの先頭に#!(sha-bang)行を使用してインタープリターを呼び出す多くの本が書かれています。これにより、スクリプトの新しいシェルが呼び出され、行ごとに解釈が行われます。私の基本的なスクリプトの一部はまだ魔法の行なしで実行されています。

だから私の質問は:

  • 基本的なスクリプトはどこからインタープリターを取得しましたか。
  • スクリプトがインタープリターを特定する方法を教えてください。

次に、基本的なスクリプトについて説明します。スクリプトには次の行が含まれています。

「魔法の線のない基本的なスクリプト」をエコー


回答:


3

magic行が指定されていない場合は、デフォルトのシェルを使用してスクリプトが実行されます。このデフォルトのシェルは、一部のフレーバーに該当するBourneシェル(sh)のいずれかですが、他の一部のフレーバーでは、使用されるデフォルトのシェルは、ログインシェルと同じで実行されます。重要なことは、システムに任せてシェルを決定するのではなく、常に最初の行に必要なシェルを指定することです。


1
yup ..たぶん、私の現在のシェルは、マジックナンバーを持たないシェルスクリプトのデフォルトシェルを呼び出しています。
user1678213

1
@ user1678213はい、これを行っているのは(カーネルではなく)シェルです。
Gilles「SO-邪悪なことをやめなさい」

1
この場合、/ bin / shを使用するようPOSIXで義務付けられていると思います。
フォンブランド2013年

2
@vonbrandこれはよくある誤解です。POSIXは、POSIXシェルをにすることを義務付けていません。準拠するPATHを探索/bin/shしているときに最初にsh見つかった実行可能ファイルになるようにしています。
jlliagre 2013

3
それは不正解です。実行に使用されるのは「ログインシェル」ではありません。ただし、呼び出し元のシェル(スクリプトがシェルから呼び出された場合)は、それ自体を解釈する子を持っている可能性があります。
ステファンChazelas

8

プログラムを実行すると、カーネルはそれが何らかの魔法のバイトシーケンスで始まるかどうかをチェックします。実行可能ファイルがで始まる場合、#!カーネルは行の残りの部分をインタープリター名として解釈します。実行可能ファイルが\177ELF\177バイト127 で始まる)で始まる場合、ELF実行可能ファイルとしてファイルをロードします。最近のほとんどのUNIXシステムでは、これが通常の種類です。

カーネルがファイル形式を認識しない場合、カーネルはファイルの実行を拒否し、エラーENOEXEC(Exec形式エラー)を返します。シェルがそれに気づくと、プログラムをシェルスクリプトとして実行する必要があります。

この動作を確認するには、スクリプトにいくつかのコマンドを追加します。

ps l $$
ls -l /proc/$$/exe
echo hello

(これはLinux用です。他のuniceに合わせて調整してください。)次に、そのスクリプトをさまざまなシェルから実行してみてください。一部のシェルは、スクリプトを実行するために自分自身の新しいインスタンスを生成します(bash、ksh93)一方で、他のシェルは生成します/bin/sh(ダッシュ、pdksh、zsh)。


ls -lコマンドで何を探しますか?これ:lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash-?もしそうなら、それは何と言いますか?また、私はを持っていることに気づきSHELL=/bin/bashましたがenv、それを変更しても動作は変更されないようです。多分それは無関係です?
Emanuel Berg

シェル変数「SHELL」を変更しているようです。「はい」の場合、シェル変数SHELLの値を変更するだけです。シェルを変更することはできません。シェルを変更するには、/ etc / passwdファイルを編集します。
user1678213 2012年

2
@EmanuelBergはい(ls -l /proc/$$/exe実際にはを書いておくべきでした)。exeスクリプトを実行するのシェルへのリンクポイント。スクリプトを実行すると、スクリプトを解釈するのはbashであることがわかります。たとえばpdkshから実行すると、が実行されます/bin/sh。そのSHELL環境で環境変数を使用するシェルやログインシェルを知りません。
Gilles「SO-悪をやめなさい」

2
@ user1678213でシェルを/etc/passwd変更すると、SSH経由またはテキストコンソールでログインしたときに実行されるシェルが変更されます。どのシェルがスクリプトを実行するかは変更されません。
Gilles「SO-悪をやめなさい」

2
@ user1678213テストを実行して、ここに書き込んだ内容を確認しました。私がテストし/etc/passwdたどのシェルも、どのシェルを使用するかを決定するために調べたものではなく、自分自身のインスタンスをforkするか、実行しました/bin/sh
Gilles「SO-邪悪なことをやめなさい」

-2

おそらく次の3つの可能性のうちの1つです。

  1. インタプリタIEを使用してスクリプトを直接呼び出しています:bash script.sh

  2. スクリプトファイルの名前には.sh拡張子が付いています。これにより、システムはこのタイプのファイルのデフォルトプログラムを検索します。

  3. スクリプトファイルが実行可能であるとしか推測できないため、使用しているシェル環境はそれ自体で「エコー」を実行しています。たとえば、bashシェルを使用していて、ファイル内にkshのみが使用するコマンドがある場合、そのコマンドは機能しないことがわかります。

幸運を!


3
私はそれをbashでも拡張機能でも呼び出しませんでした。
user1678213 2012年

1
スクリプトを呼び出した後にpsコマンドを呼び出すと、シェル環境はそれを実行しません。psコマンドは2つのbashプロセスを表示します。つまり、2つのbashが実行されています。1つは私のログインbashシェルで、もう1つは私のbasic_scriptのbashです
user1678213 '10

1
2:カーネルはそのようなことは何もしません。Zshはそれを行うことができ、bashはそれを実行するためにねじれることができます。3:はい。ただし、シェルによって多少異なります。私の答えをご覧ください。
Gilles「SO-邪悪なことをやめなさい」
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.