題 執行Bash腳本與採購它有什麼區別?


執行像A這樣的Bash腳本和採購像B這樣的Bash腳本有什麼區別?

A
> ./myscript

B
> source myscript

228
2017-12-11 15:24


起源




答案:


簡短回答:sourcing將在當前shell進程中運行命令。執行將在新的shell進程中運行命令。仍然困惑?那麼請繼續閱讀詳細的答案。

術語:

澄清有關要執行的語法和源語法的一些常見錯誤:

./myscript

執行  myscript 只要該文件是可執行的並且位於當前目錄中。領先的點斜線(./)表示當前目錄。這是必要的,因為當前目錄通常不在 $PATH

myscript

執行  myscript 如果文件是可執行的並且位於某個目錄中 $PATH

source myscript

資源  myscript。該文件不必是可執行文件,但它必須是有效的shell腳本。該文件可以位於當前目錄或目錄中 $PATH

. myscript

資源  myscript。這個語法是 由POSIX定義。 Bash定義 source 作為dot命令的別名。

示範:

考慮 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 未設置且工作目錄未更改。

腳本輸出清楚地顯示變量已設置且目錄已更改。之後的檢查顯示未設置變量且目錄未更改。發生了什麼?這些變化是在a  貝殼。該 當前 貝殼催生了一個  shell運行腳本。該腳本在新shell中運行,對環境的所有更改都在新shell中生效。腳本完成後,新shell將被銷毀。使用新shell銷毀新shell中對環境的所有更改。僅在當前shell中打印輸出文本。

現在我們 資源 文件:

$ 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並且工作目錄已更改。

採購腳本不會創建新的shell。所有命令都在當前shell中運行,對環境的更改在當前shell中生效。

請注意,在此簡單示例中,執行的輸出與獲取腳本的輸出相同。情況並非總是如此。

另一個示範:

考慮以下腳本 pid.sh

#!/bin/sh
echo $$

(特殊變量 $$ 擴展到當前運行的shell進程的PID)

首先打印當前shell的PID:

$ echo $$
25009

來源腳本:

$ source pid.sh
25009

執行腳本,注意PID:

$ ./pid.sh
25011

來源:

$ source pid.sh
25009

再次執行:

$ ./pid.sh
25013

您可以看到,在執行腳本時,腳本的源代碼運行在同一個進程中,每次都會創建一個新進程。那個新的過程就是  為執行腳本而創建的shell。獲取腳本不會創建新shell,因此PID保持不變。

摘要

採購和執行腳本都將逐行運行腳本中的命令,就像您逐行手動鍵入這些命令一樣。

不同之處是:

  • 當你 執行 你要打開的劇本  shell,在新shell中鍵入命令,將輸出複制回當前shell,然後關閉新shell。對環境的任何更改只會在新shell中生效,並且在關閉新shell後將丟失。
  • 當你 資源 您正在鍵入命令的腳本 當前 貝殼。對環境的任何更改都將生效並保留在當前shell中。

如果希望腳本更改當前運行的shell中的環境,請使用source。否則使用執行。


也可以看看:


290
2017-08-16 21:58



採購的一個用途是為腳本創建一種基本的配置文件形式。首先將各種變量設置為默認值,然後使用myscript.conf之類的源代碼 - 並且源腳本可以具有覆蓋所需值的賦值語句。由於源腳本不以#/ bin / bash開頭,因此不鼓勵直接執行它。 - LawrenceC
因此,source有點像在全局範圍內運行它,並且執行會創建一個新的本地範圍。這可以擴展到腳本中的函數嗎?執行一個函數(通常)或“源”它? - aliteralmind
使用之間有區別嗎? source myscript.sh 和 . myscript.sh? - Holloway
如果使用bash,幾乎沒有區別。 source是bash中dot的別名。 - lesmana
當人們提供如此詳盡的例子時,我喜歡它,這樣即使像我這樣的Linux新手也能理解。謝謝! - Julius


執行腳本在單獨的子進程中運行它,即調用shell的單獨實例來處理腳本。這意味著腳本中定義的任何環境變量等 不能 在父(當前)shell中更新。

獲取腳本意味著它由當前shell本身解析和執行。就好像你輸入了腳本的內容一樣。因此,源代碼不需要是可執行的。但如果你正在執行它,它必須是可執行的。

如果你在當前shell中有位置參數,它們就不會改變。

所以,如果我有一個文件 a.sh 含:

echo a $*

我這樣做:

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

我有類似的東西:

a Fri Dec 11 07:34:17 PST 2009

鑑於:

$ set `date`
$ ./a.sh

給我:

a

希望有所幫助。


21
2017-12-11 15:35



雖然這個答案在各方面都是正確的,但我覺得很難理解,因為它是用其他概念(設定位置參數)來證明的,在我看來,這比採購和執行本身的差異更令人困惑。 - lesmana


sourcing與在命令提示符下一次輸入腳本的每一行基本相同......

執行啟動一個新進程,然後運行腳本的每一行,只修改它返回的當前環境。


7
2017-12-11 15:27





採購您將獲得腳本中定義的所有額外變量。
因此,如果你有配置或函數定義,你應該來源而不是執行。執行與父母環境無關。


4
2017-12-11 15:25





除此之外, 執行腳本為 ./myscript 需要對文件myscript執行權限,而採購不需要任何執行權限。這就是為什麼 chmod +x myscript 以前不需要 source myscript


4
2018-02-23 07:27



沒錯,但如果這是一個問題,你可以隨時運行 bash myscript。 - Daniel Beck♦


如果我記得正確,執行腳本會運行可執行文件 #! 將腳本文件作為參數排列(通常啟動一個新的shell並有效地將腳本導入到新的shell中,如同 #!/bin/sh);
然而,獲取腳本會執行當前shell環境中的每一行,這對於改變當前shell很有用(例如,提供一種定義shell函數和導出環境變量的方法)。


3
2017-12-11 15:27





source 命令執行提供的腳本 (可執行權限是 不是強制性的 在裡面 當前 shell環境,而 ./ 執行提供的 可執行 腳本在  貝殼。

另外,請查看此答案,例如: https://superuser.com/a/894748/432100


2
2018-03-27 14:04