shell指令碼的三種執行方式和區別

thammer發表於2024-12-06

執行方式

  1. 直接使用絕對,相對路徑

這種是平時我們最常用的方法,例如:

./test.sh
/home/thammer/test.sh

甚至PATH目錄裡面的,如系統自帶的命令,也就是無需指定路徑,直接使用命令,也是這種形式,只不過命令在bash這個直譯器內部給補全了而已。

  1. 使用bash或者其他你係統帶的shell直譯器程式跟shell指令碼,例如:
bash test.sh
zsh ./test.sh

這種和第一種區別不大,稍微有區別的地方是,如果系統帶有多種shell直譯器,那麼這裡可以指定你想要的那種,否則用的就是預設的。

  1. 使用內建的source命令
source ./test.sh

source命令是shell內建命令,類似的還有cd,alias,fg等等。

三種方式的區別

第三種source這種方式執行shell指令碼和前兩者有非常大的區別,它直接在當前shell直譯器程序載入並執行命令,共享了當前直譯器程序的環境變數,而前兩種方式都是在當前shell直譯器程序中開子程序,另起一個shell直譯器,然後執行shell指令碼。

如何理解?首先當我們開啟一個終端,可以理解為建立並執行了一個bash程式(是否為bash和/etc/passwd的配置相關,不做分散解釋),它提供的標準輸入,標準輸出,標準出錯3個IO和使用者進行互動。如果我們執行ps命令,可以看到當前bash程式的pid。

thammer@exc:~/CLionProjects/shelltest$ ps
    PID TTY          TIME CMD
  17450 pts/1    00:00:00 bash
  19934 pts/1    00:00:00 ps

可以看到當前bash的pid為17450,那麼我們可以在shell指令碼中輸出當前程序id,就知道是開啟了子程序,還是直接在當前程序執行的shell指令碼了。在shell中,獲取當前程序id的方法是透過內建的變數$。使用$$(第一個是shell語法中引用變數的關鍵字元,第二個就是內建變數$,表示當前程序id)就獲取到了當前程序pid。test.sh如下:

#!/bin/bash
echo $$

按照3種執行方式執行,結果如下:

thammer@exc:~/CLionProjects/shelltest$ ./test.sh 
20129
thammer@exc:~/CLionProjects/shelltest$ bash test.sh 
20132
thammer@exc:~/CLionProjects/shelltest$ source test.sh 
17450

只有最後這個pid和當前bash的程序pid一樣。

有何影響

由於source未開闢新的程序,所以它可以看到當前程序的環境變數,也可以修改並影響當前bash程序的環境變數,而前兩種種方式不能。驗證,首先在當前shell命令賦值一個變數,

VAR1=hello

透過3中方式執行如下shell指令碼,test.sh

#!/bin/bash
echo $VAR1
VAR1=world

執行

thammer@exc:~/CLionProjects/shelltest$ VAR1=hello
thammer@exc:~/CLionProjects/shelltest$ ./test.sh 

thammer@exc:~/CLionProjects/shelltest$ echo $VAR1
hello
thammer@exc:~/CLionProjects/shelltest$ source ./test.sh 
hello
thammer@exc:~/CLionProjects/shelltest$ echo $VAR1
world

相關文章