調達 スクリプトは current でコマンドを実行します シェルプロセス。
実行中 スクリプトは new でコマンドを実行します シェルプロセス。
スクリプトで現在実行中のシェルの環境を変更する場合は、source を使用します。それ以外の場合は execute を使用してください。
「環境」とは、現在の作業ディレクトリや環境変数などです。また、シェル設定 (とりわけ履歴と補完機能)。他にもありますが、それらが最も目立つものです。
詳細が必要な場合は、読み進めてください。
用語
実行する構文とソースする構文に関する一般的な混乱を明確にするには:
./myscript
これは実行します myscript
ファイルが実行可能で、現在のディレクトリにある場合。先頭のドットとスラッシュ (./
) は現在のディレクトリを示します。これが必要なのは、現在のディレクトリが通常 $PATH
にない (通常はそうあるべきではない) ためです。 .
myscript
これは実行します myscript
ファイルが実行可能で、$PATH
のディレクトリにある場合 .
source myscript
これはソースになります myscript
.ファイルは実行可能である必要はありませんが、有効なシェル スクリプトである必要があります。ファイルは、現在のディレクトリまたは $PATH
のディレクトリにあります。 .
. myscript
これもソースになります myscript
.この「スペル」は、POSIX で定義されている公式のものです。 Bash で定義された source
ドットのエイリアスとして。
完全を期すために:
exec myscript
これにより、現在のシェルが終了し、終了したシェルの代わりに myscript が実行されます。つまり、myscript が完了すると、戻る古いシェルがなくなります。 exec
は強力ですが、ほとんど必要ありません。
これらのトピックの詳細については、最後にいくつかのリンクを掲載しています。
デモンストレーション
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
は定義されておらず、ホーム ディレクトリにいます。
今、実行します ファイル:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
環境をもう一度確認してください:
$ env | grep FOO
$ echo $PWD
/home/lesmana
変数 FOO
は設定されておらず、作業ディレクトリは変更されていません。
スクリプトの出力は、変数が設定され、ディレクトリが変更されたことを明確に示しています。その後のチェックでは、変数が設定されておらず、ディレクトリが変更されていないことが示されています。どうしたの?変更は new で行われました シェル。 現在 シェルは新しいを生成しました スクリプトを実行するためのシェル。スクリプトは新しいシェルで実行され、環境へのすべての変更が新しいシェルで有効になります。スクリプトが完了すると、新しいシェルは破棄されます。新しいシェルの環境に対するすべての変更は、新しいシェルで破棄されます。出力テキストのみが現在のシェルで出力されます。
今度はソース ファイル:
$ 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
スクリプトを実行すると毎回新しいプロセスが作成されますが、スクリプトの実行は同じプロセスで実行されることがわかります。その新しいプロセスは新しい スクリプトを実行するために作成されたシェル。スクリプトを取得しても新しいシェルは作成されないため、PID は同じままです。
まとめ
スクリプトのソースと実行の両方で、コマンドを 1 行ずつ手動で入力したかのように、スクリプト内のコマンドが 1 行ずつ実行されます。
違いは次のとおりです:
- いつ実行するか 新しいを開くスクリプト 新しいシェルでコマンドを入力し、出力を現在のシェルにコピーしてから、新しいシェルを閉じます。環境への変更は新しいシェルでのみ有効になり、新しいシェルを閉じると失われます。
- 情報源の場合 現在のでコマンドを入力しているスクリプト シェル。環境への変更は有効になり、現在のシェルにとどまります。
スクリプトで現在実行中のシェルの環境を変更する場合は、source を使用します。それ以外の場合は execute を使用してください。
こちらもご覧ください:
- https://stackoverflow.com/questions/6331075/why-do-you-need-dot-slash-before-script-name-to-run-it-in-bash
- https://askubuntu.com/questions/182012/is-there-a-difference-before-and-source-in-bash-after-all
- https://stackoverflow.com/questions/18351198/what-are-the-uses-of-the-exec-command-in-shell-scripts
スクリプトを実行すると、別の子プロセスで実行されます。つまり、スクリプトを処理するためにシェルの別のインスタンスが呼び出されます。これは、スクリプトで定義された環境変数などはできないことを意味します 親 (現在の) シェルで更新されます。
スクリプトのソースとは、現在のシェル自体によって解析および実行されることを意味します。まるでスクリプトの内容を入力したかのようです。このため、供給されるスクリプトは実行可能である必要はありません。ただし、もちろん実行する場合は、実行可能でなければなりません。
現在のシェルに位置引数がある場合、それらは変更されません。
ファイル a.sh
がある場合 含む:
echo a $*
$ set `date`
$ source ./a.sh
次のようなものが得られます:
a Fri Dec 11 07:34:17 PST 2009
一方:
$ set `date`
$ ./a.sh
私に与えます:
a
お役に立てば幸いです。
ソースは、基本的に、コマンド プロンプトでスクリプトの各行を 1 つずつ入力するのと同じです...
実行は新しいプロセスを開始し、スクリプトの各行を実行し、返される内容によって現在の環境のみを変更します。