シェルで この質問 の答えを調べている間、/bin/sh
がシステム上の/bin/bash
を指していても、2つのコマンドの動作が異なることに気付きました。 。まず、の出力
ls -lh /bin/sh
は:
lrwxrwxrwx 1 root root 4 Apr 22 2013 /bin/sh -> bash*
ただし、/bin/sh
を介して次のコマンドを呼び出します。
/bin/sh -c "script.sh 2> >( grep -v FILTER 2>&1 )"
このエラーを返します:
/bin/sh: -c: line 0: syntax error near unexpected token '>'
/bin/sh: -c: line 0: 'script.sh 2> >( grep -v FILTER 2>&1 )'
/bin/bash
を介して同じコマンドを実行しているとき:
/bin/bash -c "script.sh 2> >( grep -v FILTER 2>&1 )"
正常に実行されます。出力は次のとおりです。
This should be on stderr
参考のため、script.sh
の内容は次のとおりです。
#!/bin/sh
echo "FILTER: This should be filtered out" 1>&2
echo "This should be on stderr" 1>&2
echo "FILTER: This should be filtered out" 1>&2
2つの呼び出しの動作が異なるのはなぜですか?
bash
は$argv[0]
(bashはCで実装されています)の値を見て、どのように呼び出されたかを判断します。
sh
として呼び出されたときの動作は文書化されています マニュアル内 :
Bashが
sh
という名前で呼び出された場合、POSIX標準にも準拠しながら、sh
の履歴バージョンの起動時の動作を可能な限り模倣しようとします。対話型ログインシェルとして、または
-login
オプションを使用した非対話型シェルとして呼び出されると、最初に/etc/profile
および~/.profile
からこの順序でコマンドを読み取って実行しようとします。--noprofile
オプションを使用して、この動作を禁止できます。sh
という名前の対話型シェルとして呼び出された場合、Bashは変数ENV
を探し、値が定義されている場合はその値を展開し、展開した値をファイルの名前として使用して読み取り、実行します。sh
として呼び出されたシェルは、他のスタートアップファイルからコマンドを読み取って実行しようとしないため、--rcfile
オプションは効果がありません。sh
という名前で呼び出された非対話型シェルは、他のスタートアップファイルを読み取ろうとしません。
sh
として呼び出された場合、Bashは起動ファイルが読み取られた後にPOSIXモードに入ります
bash
がPOSIXモードの場合に変更されるものの長いリスト(現在46項目)があります ここに記載 。
(おそらくPOSIXモードは、_bash
以外のシェルへの移植性についてスクリプトをテストする方法として主に有用です。)
ちなみに、呼び出された名前に応じて動作を変更するプログラムはかなり一般的です。 grep
、fgrep
、およびegrep
の一部のバージョンは、単一の実行可能ファイルとして実装されます(ただし、GNU grep
は ' view
は通常vi
またはvim
へのシンボリックリンクであり、view
として呼び出すと読み取り専用モードで開きます。 Busybox systemには、マスターbusybox
実行可能ファイルへのすべてのシンボリックリンクである多数の個別のコマンドが含まれています。
Bashをsh
として呼び出すと、通常読み込まれるスタートアップファイルを読み込んだ後にposix modeになります(POSIX shが読み込むスタートアップファイルとは異なります)。モード。これらのモードについては、マニュアルのINVOCATION
セクションから確認できます。 POSIXモードについて詳しく説明します。
このモードは、bashがさまざまな程度でPOSIXの期待に準拠しようとすることを意味します。 here で説明したように、bashには、このモードに対していくつかの異なる呼び出しがあり、わずかに異なる影響があります。
sh
:起動ファイルを読み取った後、BashはPOSIXモードに入ります。bash --posix
:BashはPOSIXモードに入りますbeforeスタートアップファイルの読み取り。set -o posix
:BashはPOSIXモードに切り替わります。POSIXLY_CORRECT
:bashの起動時にこの変数が環境内にある場合、シェルはposixモードに入りますbeforebash --posix
などの起動ファイルを読み取ります。 set -o posix
のように、bashの実行中に設定されている場合。Bashがshという名前で呼び出された場合、POSIX標準にも準拠しながら、shの履歴バージョンの起動時の動作を可能な限り模倣しようとします。
bash
バイナリは、それがどのように呼び出されたかを確認するため(argv[0]
)sh
として実行されている場合、互換モードに入ります。