私はこれで以下を読みました 質問 :
bashは--posixスイッチをサポートしており、POSIXに準拠しています。 がshとして呼び出された場合も、POSIXを模倣しようとします。
上記の引用は、/bin/sh
が/bin/bash
を指すリンクであることを前提としています。
しかし、「shとして呼び出される」の意味がよくわかりません。
「script.sh」と呼ばれる次のスクリプトがあるとします。
#!/bin/bash
echo "Hello World"
スクリプトが通常のbash
モードで実行されるのか、POSIXモードで実行されるのかを、次のそれぞれのケースで教えてください(bash
を実行している端末で次のコマンドを実行したと想定します) :
sh script.sh
bash script.sh
./script.sh
「script.sh」と呼ばれる次のスクリプトがあるとしましょう(上記のスクリプトに似ていますが、シバンはありません)。
echo "Hello World"
スクリプトが通常のbash
モードで実行されるのか、POSIXモードで実行されるのかを、次のそれぞれのケースで教えてください(bash
を実行している端末で次のコマンドを実行したと想定します) :
sh script2.sh
bash script2.sh
./script2.sh
ケース1と4のみがPOSIXモードで実行されます(sh
はbashであり、shの他の実装ではないと想定)。シバンからであろうとなかろうと、--posix
なしで明示的にbash
を呼び出すケースは、実行されません。明示的にsh
を呼び出すケースはすべて発生します。 Shebangは、シェルがスクリプトに対して明示的に開始されていない場合にのみ使用されます。
ケース6、ターミナルがbash
を実行している場合、POSIXモードで実行されず、 Bashはそれ自体を使用して起動します。ターミナルがzshを実行している場合は、ケース6wouldもPOSIXモードで実行されます。POSIXはその場合に何が起こるか正確に不明確です 、そしてBashとzshは異なる選択をしました。 Bashはそれ自体を使用してスクリプトを呼び出し、zshはsh
を使用します(それが何であれ)。他のシェルもその点で異なります。
現在のモードを確認する簡単な方法の1つは、スクリプトの本文を作成することです。
kill -SIGHUP
これは POSIXモードではエラーで失敗する ですが、その外でのkill
の使用方法を示しています。これは簡単に区別でき、遭遇する可能性が高い限り、過去のBashのさまざまなバージョンで機能します。
"invoked as"は、Bashを起動するプロセスが "0番目"のコマンドライン引数_argv[0]
_に入れるものを意味します。
exec*()
syscalls を使用してプログラムを起動すると、プログラムを含むバイナリファイルの名前を実際に知ることはできませんが、代わりにプロセスは、必要なものを自由に配置できます。もちろん、通常、名前はファイルシステムから取得されます。そのため、_/bin/sh
_を実行すると、そこに配置されます。また、_/bin/sh
_がBashの場合、シンボリックリンクである必要はありません。ハードリンクまたはシェルプログラムの別のコピーである可能性があります。
「プログラム名」を設定する例として、Bashのexec
コマンドは、_-a
_オプションを使用してゼロ番目の引数を設定できます。 (Perlで同じことをすることも、Cで直接行うこともできます。)
ここで、myname
は単純なCプログラムであり、0番目の引数を表示します。
_$ ./myname
I am ./myname
$ (exec -a something ./myname )
I am something
$ mv ./myname somename
$ ln -s somename othername
$ ./somename
I am ./somename
$ ./othername
I am ./othername
_
ソース:
_#include <stdio.h>
int main(int argc, char *argv[]) {
printf("I am %s\n", argv[0]);
return 0;
}
_
しかし、番号の付いた質問に答えるために...
(1&4)_sh somescript
_を実行すると、sh
がPATH
にあるものすべてが実行されます。おそらく_/bin/sh
_ですが、 おそらく_/usr/xpg4/bin/sh
_ 。
sh
という名前が表示されるため、POSIXモードで実行されます。sh
という名前が表示されますが、「SH互換」モードで実行されます。これは、ボーンシェル互換であることを目的としており、完全なPOSIX準拠とは微妙に異なりますこれらのシェルの両方でモード。(2&5)_bash somescript
_を実行すると、通常のBashモードで実行されます(もちろん、bash
のPATH
が何であるかによって異なります)。
(3)ここでは、スクリプトの名前は、プログラムファイルの代わりにシステムコールに直接指定されます。カーネルはハッシュバン行を読み取り、それを使用してスクリプトを実行します。
(6)これは複雑な問題です。 (3)に似ていますが、プログラムを開始するためのシステムコールは失敗します(ENOEXEC (Exec format error)
)。ハッシュバング行がないためです。次に何が起こるかは、実行しているシェルがPOSIXモードのitselfであるかどうかによって異なります。 POSIXでは、POSIX準拠のシェルがENOEXEC
に応答して特定の方法で動作する必要があります。 ただし、「シェルを使用するのと同等のコマンドには、ある程度の余裕があります。呼び出された」は、異なるシェルが異なることを行うことを意味します。
/bin/sh
_を実行します。 Zシェル、Almquistシェル、およびKornシェルは、_/bin/sh
_プログラムが1つであると想定して、POSIX準拠のシェルを呼び出すことを試みています。実行されるシェルはどちらかコマンドラインで呼び出されたシェル、またはシバンで呼び出されたシェル(コマンドラインで指定されていない場合)です。
したがって、バージョン1と4はsh
で実行され、2と5はbashで実行され、6はnotを実行します(sh(および他のいくつか)をインタラクティブに使用している場合)。 Bashはスクリプトを開始します。 Kshまた。Zshはshとして起動します。
Bashが/bin/sh
にリンクされている場合、sh
として開始されたものだけがposixオプションを使用します。
スクリプトに次の行を追加して、bash kshまたはzshバージョンが実行しているかどうかを検出します。
echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"