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


11

私はこの質問で次を読んだ:

bashは--posixスイッチをサポートしているため、POSIXに準拠しています。また、shとして呼び出された場合、POSIXを模倣しようとします。

上記の引用は、それ/bin/shがを指すリンクであると仮定してい/bin/bashます。

しかし、「shとして呼び出されという意味がよくわかりません。


「script.sh」と呼ばれる次のスクリプトがあるとします。

#!/bin/bash
echo "Hello World"

スクリプトが通常bashモードで実行されるのか、POSIXモードで実行されるのかを、次のそれぞれのケースで教えてください(実行中の端末で次のコマンドを実行したと想定していますbash)。

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

「script.sh」と呼ばれる次のスクリプトがあるとしましょう(上記のスクリプトに似ていますが、シバンはありません)。

echo "Hello World"

スクリプトが通常bashモードで実行されるのか、POSIXモードで実行されるのかを、次のそれぞれのケースで教えてください(実行中の端末で次のコマンドを実行したと想定していますbash)。

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

回答:


19

ケース1と4のみがPOSIXモードで実行されます(それshがbashであり、shの他の実装ではないと想定)。シバンからであろうとなかろうと、明示的にコールbashせずに呼び出すケース--posixはありません。明示的に呼び出すすべてのケースsh。シバンは、スクリプトに対してシェルが明示的に開始されていない場合にのみ使用されます。

ケース6、ターミナルが実行中の場合bash、POSIXモードでは実行されず、Bashはそれ自体を使用してそれを呼び出します。お使いの端末が代わりのzshを実行していた場合は、ケース6は考えもPOSIXモードで実行します。POSIXはその場合に何が起こるか正確に曖昧であり、Bashとzshはそこで異なる選択をしました。Bashはそれ自体を使用してスクリプトを呼び出しますが、zshはsh(それが何であれ)を使用します。他のシェルもその点で異なります。


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

kill -SIGHUP

これはPOSIXモードではエラーで失敗しますが、そのkill外での使用方法を示します。これは簡単に区別でき、遭遇する可能性が高い限り、過去のBashのさまざまなバージョンで機能します。


3
環境変数やbashなど、POSIXモードでの実行を強制するものは他にもありPOSIXLY_CORRECTますSHELLOPTS=posix
ステファンChazelas

1
[ -o posix ]は、bashでposixモードで実行されていることを確認するためのより明白な方法です(他のシェル(yashを除く)では実行されていないため、shスクリプトで実行する必要はありません)。POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'出力yes`
ステファンChazelas

2
ケース6では、POSIXが必要とするPOSIXモードのときに、bashはそれ自体でPOSIXモードのスクリプトを呼び出します。POSIXはシバンメカニズムを指定せず、6は実行可能スクリプトを作成する唯一のPOSIX方法であり、明確に指定されています(POSIX環境では、スクリプトは準拠するshユーティリティによって解釈されることを意図しています)。
ステファンシャゼル

8

「invoked as」は、Bashを起動するプロセスが「ゼロ番目」のコマンドライン引数に入れるものを指しますargv[0]

プログラムがexec*()syscallsで開始されると、プログラムを含むバイナリファイルの名前を実際に知ることはありませんが、代わりに呼び出しプロセスは自由に必要なものを自由に配置できます。通常、名前はファイルシステムから取得されます。したがって、を実行すると/bin/sh、そこに配置されます。/bin/shBashの場合、シンボリックリンクである必要はありません。ハードリンクまたはシェルプログラムの別のコピーである可能性があります。

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

これmynameは、ゼロ番目の引数、つまり自分自身に見える名前を出力する単純な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)を実行するには、sh somescript何でも実行されますsh、あなたの上にありPATH、おそらく/bin/shしかし、のような、おそらく何か/usr/xpg4/bin/sh

  • Bashの場合、名前が表示されるため、POSIXモードで実行されますsh
  • ZシェルまたはKornシェルの場合、同様に名前shが表示されますが、Bourneシェル互換であることを目的とした「SH互換」モードで実行され、両方のシェルの完全なPOSIX準拠モードとは微妙に異なります。
  • もちろん、Almquistシェル、実際のBourneシェル、または他の何かです。

(2&5)Running bash somescriptは通常のBashモードで実行されます(これももちろんbash、自分の状態によって異なりますPATH)。

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

(6)これは複雑なものです。(3)に似ていますが、プログラムを開始するためのシステムコールは失敗します(ENOEXEC (Exec format error))。これは、hashbang行がないためです。次に何が起こるかは、実行しているシェル自体がPOSIXモードであるかどうかによって異なります。POSIXでは、POSIX準拠のシェルがに応じて特定の方法で動作する必要がありENOEXECます。 ただし、「シェルを起動するのと同等のコマンド」には多少の余裕があります。つまり、シェルが異なれば異なることを行います。

  • Bourne Againシェルは、最初のコマンドライン引数としてスクリプトの名前を使用して、同じモード自分自身を再実行します。POSIX準拠モードでは、もちろんPOSIX準拠モードで自身を実行するため、POSIX準拠のシェルを呼び出すというPOSIX要件に従います。
  • Zシェル、Almquistシェル、Kornシェル/bin/shは、最初のコマンドライン引数として、他の引数の前に挿入されたスクリプトの名前で実行されます。Zシェル、Almquistシェル、およびKornシェルは、/bin/shプログラムが1 であると仮定することにより、POSIX準拠のシェルを呼び出す(試行する)ことです。

このCプログラムのソースコードを教えてください
。– GypsyCosmonaut

int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
Stig Hemmer、2018年

それだけです。
ilkkachu 2018年

4

実行されるシェルは、コマンドラインで呼び出されたシェル、またはシバンで実行されたシェルです(コマンドラインで指定されていない場合)。

したがって、バージョン1と4はで実行されsh、2と5はbashで実行され、sh(および他のいくつか)をインタラクティブに使用している場合、6は実行されない可能性があります。Bashはスクリプトを開始します。Kshも。Zshはshとして起動します。

shbashがにリンクされて/bin/shいる場合、posixオプションを使用するのは、として開始されたものだけです。

スクリプトに次の行を追加して、bash kshまたはzshバージョンが実行しているかどうかを検出します。

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.