Bashスクリプトの実行とソースの違いは何ですか?


回答:


346

簡潔な答え

スクリプトをソースすると、現在のシェルプロセスでコマンドが実行されます。

実行スクリプトは、内のコマンドを実行します新しいシェルプロセス。

スクリプトで現在実行中のシェルの環境を変更する場合は、ソースを使用します。それ以外の場合はexecuteを使用します。

まだ混乱している場合は、読んでください。

用語

実行する構文とソースの構文に関する一般的な混乱を明確にするには:

./myscript

これは、ファイルが実行可能で、現在のディレクトリにある場合に実行 myscriptされます。先頭のドットとスラッシュ(./)は、現在のディレクトリを示します。これは、現在のディレクトリが通常ではない(通常はそうではない)ために必要$PATHです。

myscript

これは、ファイルが実行可能で、のディレクトリにある場合に実行さ myscript$PATHます。

source myscript

これはソースに なりますmyscript。ファイルは実行可能である必要はありませんが、有効なシェルスクリプトでなければなりません。ファイルは、現在のディレクトリまたはのディレクトリにあり$PATHます。

. myscript

これもソースになり myscriptます。この「スペル」は、POSIXで定義されている公式のものです。sourceドットのエイリアスとして定義されたbash 。

デモンストレーション

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は設定されておらず、作業ディレクトリは変更されていません。

スクリプト出力は、変数が設定され、ディレクトリが変更されたことを明確に示しています。その後のチェックは、変数が設定されておらず、ディレクトリが変更されていないことを示しています。どうした?変更は新しいシェルで行われました。現在のシェルが起動され、新たなスクリプトを実行するシェルを。スクリプトは新しいシェルで実行されており、環境へのすべての変更は新しいシェルで有効になります。スクリプトの実行後、新しいシェルは破棄されます。新しいシェルの環境に対するすべての変更は、新しいシェルで破棄されます。現在のシェルでは、出力テキストのみが印刷されます。

次に、ファイルをソースします。

$ 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行ずつ実行します。

違いは次のとおりです。

  • 新しいシェルを開くスクリプトを実行する場合、新しいシェルにコマンドを入力し、出力を現在のシェルにコピーして、新しいシェルを閉じます。環境への変更は、新しいシェルでのみ有効になり、新しいシェルが閉じられると失われます。
  • あなたはときにソースのスクリプトを、あなたのコマンドを入力している現在のシェル。環境への変更はすべて有効になり、現在のシェルに残ります。

スクリプトで現在実行中のシェルの環境を変更する場合は、ソースを使用します。それ以外の場合はexecuteを使用します。


こちらもご覧ください:


2
ソースの1つの使用法は、スクリプト用の基本的な構成ファイルの作成です。さまざまな変数をデフォルト値に設定してから、myscript.confなどのソースを作成します。ソーススクリプトには、必要な値をオーバーライドする割り当てステートメントを含めることができます。ソーススクリプトは#/ bin / bashで始まっていないため、直接実行することはお勧めしません。
ローレンス

したがって、ソースはグローバルスコープで実行するようなもので、実行すると新しいローカルスコープが作成されます。これをスクリプト内の関数に拡張できますか?関数を(通常)実行するか、それを「ソース」するか?
aliteralmind

2
使用しての間に違いがあるsource myscript.shとは. myscript.sh
ホロウェイ

2
bashを使用する場合、実質的に違いはありません。sourceは、bashのドットのエイリアスです。
レスマナ

1
私のようなLinux初心者でも理解できるように、人々がそのような精巧な例を提供するのが大好きです。ありがとう!
ジュリアス

21

スクリプトを実行すると、別の子プロセスで実行されます。つまり、シェルの別のインスタンスが呼び出されて、スクリプトが処理されます。つまり、スクリプトで定義されている環境変数などは、親(現在の)シェルでは更新できません

スクリプトのソースは、現在のシェル自体によって解析および実行されることを意味します。スクリプトの内容を入力したかのようです。このため、ソースとなるスクリプトは実行可能である必要はありません。ただし、もちろん実行する場合は実行可能でなければなりません。

現在のシェルに位置引数がある場合、それらは変更されません。

だから私がa.sh含むファイルがある場合:

echo a $*

そして私は:

$ set `date`
$ source ./a.sh

私は次のようなものを得ます:

a Fri Dec 11 07:34:17 PST 2009

一方、

$ set `date`
$ ./a.sh

私に与えます:

a

お役に立てば幸いです。


5
この答えはあらゆる点で正しいですが、別のコンセプト(位置パラメータの設定)を使用して示されているため、理解するのは非常に難しいと思いますが、これはソーシングと実行の違いよりもさらに混乱しています。
レスマナ

9

ソースは、コマンドプロンプトでスクリプトの各行を1つずつ入力するのと基本的に同じです...

実行すると、新しいプロセスが開始され、スクリプトの各行が実行されます。現在の環境は、返される内容によってのみ変更されます。


6

上記に加えて、スクリプトを実行するには./myscriptmyscriptファイルの実行権限が必要ですが、ソースには実行権限は必要ありません。それがchmod +x myscript前に必要ではない理由ですsource myscript


2
確かに、しかしそれが問題であれば、いつでも実行できますbash myscript
ダニエルベック

5

スクリプトで定義されたすべての追加変数を取得します。
そのため、構成または関数定義がある場合は、実行せずにソースする必要があります。実行は、親環境から独立しています。


3

正しいことを思い出すと、スクリプトを実行する#!と、スクリプトファイルを引数として持つ行で実行可能ファイルが実行されます(通常、新しいシェルを開始し、のようにスクリプトを新しいシェルに効率的にソースします#!/bin/sh)。
一方、スクリプトをソースすると、現在のシェル環境の各行が実行されます。これは、現在のシェルを変更するのに便利です(たとえば、シェル関数を定義して環境変数をエクスポートする方法を提供します)。


2

sourceコマンドが提供されたスクリプトを実行(実行可能権限がある必須ではありません、現在ながら、シェル環境を./提供する実行実行中のスクリプト新しいシェルを。

また、次の例の回答を確認してください:https : //superuser.com/a/894748/432100

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