AのようなBashスクリプトを実行することとBのようなBashスクリプトを調達することの違いは何ですか?
A
> ./myscript
B
> source myscript
Sourcingスクリプトは、currentShellプロセス内のコマンドを実行します。
スクリプトを実行すると、newShellプロセスでコマンドが実行されます。
あなたがまだ混乱しているならば、読んでください。
実行する構文とソースへの構文に関する一般的な混乱を明確にするには、次のようにします。
./myscript
これはexecutemyscript
になります。ただし、ファイルが実行可能であり、現在のディレクトリにあると仮定します。先頭のドットとスラッシュ(./
)は現在のディレクトリを表します。現在のディレクトリは通常$PATH
には含まれていないので(そして通常はそうすべきではありません)、これは必要です。
myscript
ファイルが実行可能で$PATH
のあるディレクトリにある場合、これはexecutemyscript
になります。
source myscript
これはsourcemyscript
になります。ファイルは実行可能ファイルである必要はありませんが、有効なシェルスクリプトである必要があります。ファイルは現在のディレクトリまたは$PATH
内のディレクトリにあります。
. myscript
これはsourcemyscript
にもなります。この「綴り」は POSIX で定義されている公式のものです。 Bashはsource
をドットの別名として定義しました。
以下の内容のmyscript.sh
を考えます。
#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD
最初にスクリプトを実行する前に、現在の環境を確認します。
$ env | grep FOO
$ echo $PWD
/home/lesmana
変数FOO
が定義されておらず、ホームディレクトリにいます。
今executeファイル:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
環境をもう一度確認してください。
$ env | grep FOO
$ echo $PWD
/home/lesmana
変数FOO
が設定されておらず、作業ディレクトリも変更されていません。
スクリプトの出力は、変数が設定され、ディレクトリが変更されたことを明確に示しています。その後のチェックは、変数が設定されておらず、ディレクトリも変更されていないことを示しています。何が起こった?変更はnewShellで行われました。currentShellは、newShellを生成してスクリプトを実行しました。スクリプトは新しいシェルで実行されており、環境に対するすべての変更は新しいシェルで有効になります。スクリプトが実行された後、新しいシェルは破壊されます。新しいシェルの環境に対するすべての変更は、新しいシェルによって破棄されます。出力テキストだけが現在のシェルに表示されます。
今sourceファイル:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
環境をもう一度確認してください。
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
変数FOOが設定され、作業ディレクトリが変更されました。
スクリプトを入手しても新しいシェルは作成されません。すべてのコマンドは現在のシェルで実行され、環境への変更は現在のシェルで有効になります。
この簡単な例では、実行の出力はスクリプトの取得と同じです。これは必ずしもそうとは限らない。
以下のスクリプトpid.sh
を考えてください。
#!/bin/sh
echo $$
(特殊変数$$
は、現在実行中のシェルプロセスのPIDに展開されます)
最初に現在のシェルのPIDを表示します。
$ echo $$
25009
スクリプトを入手します。
$ source pid.sh
25009
スクリプトを実行し、PIDを書き留めます。
$ ./pid.sh
25011
もう一度ソース:
$ source pid.sh
25009
再度実行してください。
$ ./pid.sh
25013
スクリプトの実行中に同じプロセスでスクリプトのソースを実行すると、毎回新しいプロセスが作成されることがわかります。その新しいプロセスは、スクリプトの実行用に作成されたnewシェルです。スクリプトを入手しても新しいシェルは作成されないため、PIDは変わりません。
スクリプトの実行と実行の両方で、あたかも手動で1行ずつコマンドを入力した場合と同様に、スクリプト内のコマンドが1行ずつ実行されます。
違いは次のとおりです。
スクリプトを実行しているシェルの環境を変更する場合は、sourceを使用してください。それ以外の場合はexecuteを使用してください。
また見なさい:
スクリプトを実行すると、別の子プロセスでスクリプトが実行されます。つまり、スクリプトを処理するためにShellの別のインスタンスが呼び出されます。つまり、スクリプトで定義されている環境変数などは、親(現在の)シェルでは更新できません。
スクリプトを調達するということは、それが現在のシェル自体によって解析および実行されることを意味します。スクリプトの内容を入力したのと同じです。このため、提供されるスクリプトは実行可能である必要はありません。しかし、もちろんそれを実行しているのなら、それは実行可能でなければなりません。
現在のシェルに位置引数がある場合、それらは変わりません。
だから私はa.sh
を含むファイルがあるなら:
echo a $*
そして私はします:
$ set `date`
$ source ./a.sh
私は何かのようになる:
a Fri Dec 11 07:34:17 PST 2009
一方、
$ set `date`
$ ./a.sh
私にくれます:
a
それが役立つことを願っています。
ソーシングは基本的には、コマンドプロンプトでスクリプトの各行を1行ずつ入力するのと同じです。
実行は新しいプロセスを開始してからスクリプトの各行を実行し、現在の環境をそれが返すものだけで変更します。
上記に加えて、./myscript
としてスクリプトを実行するには、ファイルmyscriptに対する実行権限が必要ですが、調達には実行権限は必要ありません。 chmod +x myscript
がsource myscript
の前に必要ないのはそのためです。
調達すると、スクリプトで定義されたすべての追加の変数が得られます。
それでもしあなたが設定や関数定義を持っているならば、あなたは実行するべきではなく調達すべきです。実行は両親の環境から独立しています。
思い出してみると、スクリプトを実行すると、スクリプトファイルを引数として、#!
行の実行可能ファイルが実行されます(通常は、新しいシェルを起動し、#!/bin/sh
の場合と同じようにスクリプトを新しいシェルに送ります)。
一方、スクリプトを読み込むと現在のシェル環境の各行が実行されます。これは、現在のシェルを変更するのに役立ちます(たとえば、シェル関数を定義して環境変数をエクスポートする方法を提供します)。
source
コマンドは、提供されたスクリプトを実行します(実行許可は必須ではありません)currentShell環境、./
はnewShellで提供されたexecutableスクリプトを実行します。
また、例えば、この答えを確認してください。 https://superuser.com/a/894748/432100