「/bin/sh」が「/bin/bash」を指すときにシェルスクリプトを実行する

「/bin/sh」が「/bin/bash」を指すときにシェルスクリプトを実行する

私はこのコンテンツから次の内容を読みました。質問:

bash は --posix スイッチをサポートしているため、POSIX との互換性が高くなります。また、次の場合はPOSIXを模倣しようとします。shと呼ばれる

上記の引用はへの/bin/shリンクと見なされます/bin/bash

しかし、それがどういう意味なのかよく理解できません。「shに電話して」


「script.sh」という次のスクリプトがあるとしましょう。

#!/bin/bash
echo "Hello World"

次のいずれの場合も、スクリプトが通常モードまたはPOSIXモードで実行されているかどうかを教えてくださいbash(実行中の端末で次のコマンドを実行するとしますbash)。

  1. sh script.sh
  2. bash script.sh
  3. ./script.sh

それでは、「script.sh」という次のスクリプトがあるとします(上記のスクリプトと似ていますが、shebangはありません)。

echo "Hello World"

次のいずれの場合も、スクリプトが通常モードまたはPOSIXモードで実行されているかどうかを教えてくださいbash(実行中の端末で次のコマンドを実行するとしますbash)。

  1. sh script2.sh
  2. bash script2.sh
  3. ./script2.sh

答え1

ケース1と4のみがPOSIXモードで実行されます(shbashを想定し、shの他の実装は仮定しません)。 shebangでも、どうでも構いませんが、bashWithoutへの明示的な呼び出しです。--posixwillが明示的に呼び出されるすべての状況sh。 shebang は、スクリプトに対してシェルが明示的に起動されていない場合にのみ使用されます。

ケース6、端末が実行されている場合はbashPOSIXモードで実行されていません。Bashは自分自身を使ってそれを呼び出します。端末がzshを実行している場合のケース6会議POSIXモードでも動作します。 POSIXは、この場合、正確に何が起こるのか不明です。、Bashとzshはそこで別の選択をします。 Bashは独自にスクリプトを呼び出しますが、zshはsh(何が起こっても)使用します。他のシェルもこの点で異なります。


現在どのモードにあるかを確認する簡単な方法は、スクリプト本文を作成することです。

kill -SIGHUP

これはPOSIXモードでエラーが原因で失敗するkillしかし、使用のための外部指示を提供します。これは、広範なBashバージョンに適用される単純な区別であり、発生する可能性のあるバージョンに戻ります。

答え2

「呼び出し側」は、Bashを起動するプロセスが「0番目」のコマンドライン引数に入力するすべてを示しますargv[0]

プログラムが始まるとexec*()システムコール、彼らは実際にプログラムを含むバイナリの名前を知りませんが、呼び出しプロセスはあなたが望むものを自由に入れることができます。もちろん、通常、名前はファイルシステムから取得されるため、実行すると、/bin/shその名前がそのファイルシステムに入力されます。 Bashなら、/bin/shシンボリックリンクである必要はありません。ハードリンクでも、シェルプログラムの別のコピーでもかまいません。

「プログラム名」設定の例として、Bashのexecコマンドはオプションを使用して0番目の引数を設定できます-a。 (PerlまたはCなどを使用して同じことを実行できます。)

以下は、myname0番目の引数、つまり表示される名前を印刷する単純なCプログラムです。

$ ./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)runはあなたが持っているすべてをsh somescript実行します。しかし、おそらくshPATH/bin/shこれもできます/usr/xpg4/bin/sh

  • Bashの場合は名前が表示されるため、POSIXモードで実行されますsh
  • ZシェルまたはKornシェルの場合、名前も表示されますが、shBourneシェルと互換性があるように設計された「SH互換性」モードで実行され、POSIX適合モード全体とは若干異なります。その2つの殻は異なります。
  • もちろん、Almquistシェル、実際のBourneシェル、または他のものでもかまいません。

(2&5) はbash somescript通常の Bash モードで実行されます。 (もちろんコンテンツによって異なりますbashPATH

(3) ここでは、プログラムファイルの代わりにスクリプト名をシステムコールに直接提供します。カーネルはhashbang行を読み取り、それを使用してスクリプトを実行します。

(6) これは複雑な問題である。 (3)と似ていますが、ENOEXEC (Exec format error)ハッシュバンクラインがないため、プログラムを起動するシステムコールが失敗します()。次のことは、実行中のシェルが次のものかどうかによって異なります。それ自体POSIXモードで。POSIXでは、特定の方法で応答するためにPOSIX互換シェルが必要ですENOEXEC しかし、「シェルを呼び出すのと同じコマンド」には少し余裕があります。これは、他のシェルが異なる操作を実行することを意味します。

  • ボンアイデンティティシェル同じモードでやり直す最初のコマンドライン引数としてスクリプト名を指定します。 POSIX準拠モードではなくPOSIX準拠モードで独自に実行されるため、POSIX準拠シェル呼び出しのPOSIX要件に準拠しています。
  • Zシェル、Almquistシェル、およびKornシェルは、/bin/sh他のパラメータの前に最初のコマンドライン引数として挿入されたスクリプト名を使用して実行されます。 Zシェル、Almquistシェル、およびKornシェル(試行)は、/bin/shプログラムがPOSIX互換シェルであると仮定してPOSIX互換シェルを呼び出します。

答え3

実行シェルは誰でもコマンドラインから呼び出されたもの、またはコマンドラインで指定されていない場合は、shebangから呼び出されたものです。

したがって、バージョン1と4は実行されsh、バージョン2と5はbashを使用して実行でき、バージョン6は以下を使用して実行できます。いいえsh(およびその他の一部)を対話式に使用する場合は、を実行します。 Bashはスクリプトを起動します。けしもよ。 Zshはshで始まります。

shbashが接続されている場合は、asで始まったもののみposixオプションを使用します/bin/sh

bash kshまたはzshのバージョンが実行されていることを確認するには、スクリプトに次の行を追加します。

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"

関連情報