Bash スクリプトの実行とソースの違いは何ですか?
AのようなBashスクリプトを実行するのと、BのようなBashスクリプトをソースするのは何が違うのでしょうか?
A
> ./myscript
B
> source myscript
ソース スクリプトは current シェルプロセスでコマンドを実行します。
Executing スクリプトは new シェルプロセスでコマンドを実行します。
現在実行中のシェルの環境を変更させたい場合はsourceを使用してください。
まだ混乱している場合は、先を読んでください。
./myscript
myscript
これは、ファイルが実行可能でカレントディレクトリ内にある場合に限り、 実行 myscript
となります。先頭のドットとスラッシュ (./
) はカレントディレクトリを示します。これは、カレントディレクトリは通常$PATH
には存在しない(すべきではない)ため、必要です。
source myscript
これは、ファイルが実行可能であり、myscript
のどこかのディレクトリにある場合に 実行 $PATH
を実行します。
. myscript
これはソース myscript
を生成する。ファイルは実行可能である必要はありませんが、有効なシェルスクリプトでなければなりません。ファイルはカレントディレクトリまたは$PATH
のディレクトリにあります。
#!/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
これも ソース myscript
となります。この「スペル」は POSIX で定義されている公式のものです。Bash はドットの別名として source
を定義しています。
myscript.sh
を以下の内容で考えてみます。
$ env | grep FOO
$ echo $PWD
/home/lesmana
スクリプトを実行する前に、まず現在の環境を確認します。
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
変数FOO
は定義されておらず、ホームディレクトリにあります。
$ env | grep FOO
$ echo $PWD
/home/lesmana
FOO
変数pid.sh
が定義されておらず、ホームディレクトリにあります。
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
環境を再度チェックしてみます:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
変数 $$
が設定されておらず、作業ディレクトリも変更されていません。
スクリプトの出力を見ると、明らかに変数が設定されており、ディレクトリが変更されていることがわかります。その後のチェックでは、変数が設定されておらず、ディレクトリも変更されていないことがわかります。何が起こったのでしょうか?変更はnewシェルで行われました。currentシェルはスクリプトを実行するためにnew_シェルをスポーンしました。スクリプトは新しいシェルで実行されており、環境へのすべての変更は新しいシェルで有効になります。スクリプトの実行後、新しいシェルは破棄されます。新しいシェルでの環境へのすべての変更は、新しいシェルで破棄されます。現在のシェルでは出力テキストのみが印刷されます。
ここでソースファイルを作成します。
#!/bin/sh
echo $$
$ echo $$
25009
環境を再度確認します:
$ source pid.sh
25009
変数fooが設定され、作業ディレクトリが変更されています。
スクリプトをソースしても新しいシェルは作成されません。すべてのコマンドは現在のシェルで実行され、環境への変更は現在のシェルで有効になります。
この単純な例では、実行時の出力はスクリプトのソースコードと同じであることに注意してください。これは必ずしもそうとは限りません。
以下のスクリプト 0x6& を考えてみましょう。
$ ./pid.sh
25011
(特殊変数0x6&は現在実行中のシェルプロセスのPIDに展開)
最初に現在のシェルのPIDを表示する:
$ source pid.sh
25009
スクリプトのソース。
$ ./pid.sh
25013
スクリプトを実行して PID を記録する:
0x1&
ソースを再度実行する:
0x1&
スクリプトを再度実行する:
0x1&
スクリプトをソースとして実行すると同じプロセスで実行される一方で、スクリプトを実行すると毎回新しいプロセスが作成されることがわかります。この新しいプロセスは、スクリプトの実行のために作成された new シェルです。スクリプトのソースを実行しても新しいシェルは作成されないので、PIDは同じままです。
スクリプトのソースを実行しても、スクリプトを実行しても、まるで手でコマンドを一行一行入力したかのように、スクリプト内のコマンドが一行一行実行されます。
違いは以下の通りです。
現在実行中のシェルの環境を変更したい場合は source を使用してください。
参照。
スクリプトを実行すると、スクリプトは別の子プロセスで実行されます。これは、スクリプトで定義された環境変数などは、親(現在の)シェルでは更新できないことを意味します。
スクリプトをソースするということは、現在のシェル自体がスクリプトを解析して実行することを意味します。あたかもスクリプトの内容を入力したかのようになります。このため、ソースとなるスクリプトは実行可能である必要はありません。しかし、もちろん実行しているのであれば実行可能でなければなりません。
現在のシェルに位置引数がある場合、それは変更されません。
echo a $*
を含むファイル a.sh
があって、それを実行したとします。
$ set `date`
$ source ./a.sh
を実行すると、以下のようになります。
a Fri Dec 11 07:34:17 PST 2009
のようになります。
$ set `date`
$ ./a.sh
とすると次のようになります:
a
となります。
sourcing は基本的に、コマンドプロンプトでスクリプトの各行を一度に一つずつ入力するのと同じです…
実行は新しいプロセスを開始し、スクリプトの各行を実行します。
ソースを実行すると、スクリプト内で定義されている余分な変数をすべて取得します。
なので、設定や関数の定義がある場合は、実行ではなくソースを取るべきです。実行は親環境から独立しています。
source
コマンドは現在のシェル環境で提供されたスクリプト(実行許可は必須ではありません )を実行し、./
は新しいシェルで提供された実行可能なスクリプトを実行します。
また、この回答を例として確認してみてください。 https://superuser.com/a/894748/432100