bash4.3 # pwd
/bin
bash4.3 # ll sh
lrwxrwxrwx. 1 root root 4 May 17 22:22 sh -> bash
bash4.3 # ll bash
-rwxr-xr-x. 1 root root 1072056 May 17 22:22 bash
bash4.3 # bash
bash4.3 # sh
sh-4.3#
私のOSはFedora24(デフォルトのGNOMEバージョン)です。
例から、次のことがわかります。/bin
の下で、bash
はバイナリ実行可能ファイルです。 sh
はbash
へのソフトリンクです。
したがって、私の知る限り、type bash and press enter
はtype sh and press enter
とまったく同じ結果をもたらすはずです。
type bash and press enter
すると、期待どおり[root@localhost bin]#
が得られます。
しかし、私がtype sh and press enter
の場合、驚くべきことにsh-4.3#
を取得します。
原因は何ですか?
これは文書化された機能です。
sh
という名前のシンボリックリンクを介してbashを実行すると、bashはsh
互換モードで起動します。
man bash
から:
Bashがshという名前で呼び出された場合、POSIX標準にも準拠しながら、shの履歴バージョンの起動動作を可能な限り模倣しようとします。対話型ログインシェル、または--loginオプションを指定した非対話型シェルとして呼び出されると、最初に/ etc/profileおよび〜/ .profileからコマンドをこの順序で読み取って実行しようとします。 --noprofileオプションを使用して、この動作を禁止できます。 shという名前の対話型シェルとして呼び出されると、bashは変数ENVを検索し、定義されている場合はその値を展開し、展開された値を読み取りおよび実行するファイルの名前として使用します。 shとして呼び出されたシェルは、他のスタートアップファイルからコマンドを読み取って実行しようとしないため、-rcfileオプションは効果がありません。 shという名前で呼び出された非対話型シェルは、他のスタートアップファイルを読み取ろうとしません。 shとして呼び出されると、bashはスタートアップファイルが読み取られた後にposixモードに入ります。
Cプログラムの場合は、argv[0]
を検査できます。シェルまたはPerlスクリプトの場合、$0
を検査できます。
例として、この単純なシェルスクリプトを考えてみましょう。
$ cat utc
#!/bin/sh
case "${0##*/}" in
utc) date -u ;;
et) TZ=US/Eastern date ;;
esac
$0
は、スクリプトが呼び出された名前です。 ${0##*/}
は、ディレクトリ名を削除してスクリプトが呼び出された名前です。
このシンボリックリンクを作成しましょう:
ln -s utc et
したがって、utc
とet
はどちらも同じ実行可能ファイルを実行しますが、結果は異なります。 utc
として実行すると、ユニバーサル時間が出力されます。 et
として実行すると、米国東部時間を出力します。例えば:
$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016