Shebangはスクリプトが実行されるシェルを決定しますか?

Shebangはスクリプトが実行されるシェルを決定しますか?

愚かな質問かもしれませんが、それでも聞いてみましょう。シェバンを宣言したら

#!/bin/bash 

したがって、常にmy_shell_script.shbashを使用してこのスクリプトを呼び出す必要があります。

[my@comp]$bash my_shell_script.sh

あるいは、例えば使用することができる。

[my@comp]$sh my_shell_script.sh

私のスクリプトは、shebangを使用してどのシェルが実行されているかを確認しますか?シェルでも同じことが起こりますかksh?私はAIXを使用しています。

答え1

これシェルボーン #!人間が読めるインスタンスです。マジックナンバー実行するファイルがスクリプトかバイナリファイルであるかを判断するために関数系0x23 0x21で使用されるバイト文字列で構成されています。exec()Shebangが存在する場合、exec()Shebangの後に指定された実行可能ファイルが実行されます。

これは、次のようにコマンドラインでインタプリタを指定してスクリプトを呼び出すことを意味します。両方質問に与えられた状況は、exec()コマンドラインで指定されたインタプリタを実行し、スクリプトを表示しません。

exec()したがって、他の人が指摘したように、shebang行で指定されたインタプリタを呼び出すには、スクリプトが実行可能ビットを設定して次のように呼び出す必要があります./my_shell_script.sh

この動作は、次のスクリプトを使用して簡単に説明できます。

#!/bin/ksh
readlink /proc/$$/exe

説明する:

  • #!/bin/kshksh通訳者として定義されます。

  • $$現在のプロセスのPIDを保存します。

  • /proc/pid/exeプロセス実行可能ファイルへのシンボリックリンクです(少なくともLinuxでは、AIXでは、/proc/$$/object/a.outは実行可能ファイルへのリンクです)。

  • readlinkシンボリックリンクの値を出力します。

例:

ノート:基本シェルが/bin/shシンボリックリンクであるUbuntuでこれを実演しました。スプリントつまり、シンボリックリンク/bin/dashとシンボリックリンクです。/bin/ksh/etc/alternatives/ksh/bin/pdksh

$ chmod +x getshell.sh
$ ./getshell.sh 
/bin/pdksh
$ bash getshell.sh 
/bin/bash
$ sh getshell.sh 
/bin/dash

答え2

はい、そうです。ところで、これは愚かな質問ではありません。私の答えへの参照は次のとおりです。ここ。 #でスクリプトを始めましょう!

  • これをshebangまたは「bang」ラインと呼びます。

  • Bashインタプリタの絶対パスにすぎません。

  • これは、数字記号と感嘆符文字(#!)の後に通訳者へのフルパス(たとえば/ bin / bash)で構成されます。

    Linuxのすべてのスクリプトは、最初の行で指定されたインタプリタを使用して実行されます。ほとんどすべてのbashスクリプトは通常#!/ bin / bashで始まります(Bashが/ binにインストールされていると仮定)。他のシェルで実行している場合も同様です。 ShebangはBell LabsのUnixバージョン7と8の間にDennis Ritchieによって導入されました。その後、Berkeley BSDファミリーにも追加されました。

通訳者ライン無視(shebang)

インタプリタ行が指定されていない場合、デフォルトは通常/bin/shです。ただし、 #!/bin/bash 行を設定することをお勧めします。

答え3

execLinuxカーネルのシステムコールは基本的にshebangを理解します(#!)。

私はOPがAIXについて尋ねるのを見ませんでした。 Linuxについて私が知っていることを話し、そこに強力なたとえ話があると確信するか、少なくともLinuxを探しているほとんどのGoogleの従業員を満足させるでしょう:-)

Bashで以下を行うとき:

./something

Linuxでは、execpathを使用してシステムコールを呼び出します./something

次のカーネル行は、次に渡されたファイルから呼び出されますexechttps://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

ファイルの最初のバイトを読み取り、それを#!

比較がtrueの場合、残りの行はLinuxカーネルによって解析され、パスとexec現在/usr/bin/env pythonのファイルを最初の引数として使用して別の呼び出しが行われます。

/usr/bin/env python /path/to/script.py

これは、#コメント文字として使用されるすべてのスクリプト言語に適用されます。

はい、次のように無限ループを作成できます。

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

Bashはエラーを認識しました。

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#!人が読むことができますが、必須ではありません。

ファイルが別のバイトで始まる場合、execシステムコールは別のハンドラを使用します。もう1つの最も重要な組み込みハンドラは、ELF実行可能ファイル用です。https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305バイトを確認します7f 45 4c 46(人が読むこともあります.ELF)。/bin/lsELF実行可能ファイルである最初の4バイトを読み、それを確認してみましょう。

head -c 4 "$(which ls)" | hd 

出力:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

したがって、カーネルはこれらのバイトを表示するとELFファイルをインポートし、メモリに正しく保存し、それを使用して新しいプロセスを開始します。また見なさい:https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861

最後に、このbinfmt_miscメカニズムを使用して独自のshebangハンドラを追加できます。たとえば、次のように追加できます。.jarファイルのカスタムハンドラ。このメカニズムはファイル拡張子固有の処理もサポートします。別のアプリケーションはQEMUを使用してさまざまなアーキテクチャの実行可能ファイルを透過的に実行する

しかし、POSIXはshebangを指定しないと思います。https://unix.stackexchange.com/a/346214/32558、理論的根拠セクションでこれについて言及していますが、「システムが実行可能なスクリプトをサポートすると何が起こる可能性があります」という形式で表示されます。

答え4

私が収集したものから、ファイルに実行可能ビットが設定されていて呼び出されるたびに、カーネルはファイルヘッダーを解析して進行方法を決定します(私が知る限り、LKMを介してカスタムファイル形式のカスタムハンドラを追加できます)あり)。ファイルが先頭に#!を含むテキストファイルの組み合わせとして表示されると、その実行は指定された同じ行からそのshebangの直後にパスを持つ別の実行可能ファイル(通常は一種のシェル)に渡されます。その後、カーネルはシェルを実行し、処理のためにファイルを渡します。

簡単に言えば、スクリプトを呼び出すためにどのシェルが使用されるかは問題ではありません。いずれにしても、カーネルは実行を適切なシェルに渡します。

関連情報