1. 程式人生 > >Linux shell執行source和 . 的區別

Linux shell執行source和 . 的區別

一般Linux上執行一個shell指令碼,有如下幾種方法:

 bash test.sh
 source test.sh
 . test.sh
 ./test.sh

source 和 .

source和 . 這兩個都是shell自帶的內建命令,這兩個命令是等價的關係。也就是說

source test.sh
. test.sh

這兩條命令的執行是完全一樣的。
使用type來看下命令型別:

[email protected]:~/work/test/linuxshell$ type source
source 是 shell 內建
[email protected]
:~/work/test/linuxshell$ type . . 是 shell 內建

使用help來檢視命令介紹:

 [email protected]:~/work/test/linuxshell$ help .
.: . 檔名 [引數]
    在當前 shell 中執行一個檔案中的命令。
    
    在當前 shell 中讀取並執行 FILENAME 檔案中的命令。$PATH 變數中的
    條目被用於尋找包含 FILENAME 檔案的目錄。如果提供了任何的 ARGUMENTS
    引數,則它們將成為 FILENAME 檔案執行時的位置引數。
    
    退出狀態:
    返回 FILENAME 檔案中最後一個命令的狀態;如果 FILENAME 檔案不可讀則失敗。

這兩個命令是會由父shell建立子程序去執行shell指令碼,並且特別關鍵的一點,它會繼承所有父shell的環境變數。
使用如下命令進行測試:

#!/bin/bash

echo "Print Bash Path:$SHELL"

echo $EXPORT_VAR
echo $LOCAL_VAR

執行如下:

[email protected]cheng:~/work/test/linuxshell$ LOCAL_VAR=local
[email protected]:~/work/test/linuxshell$ export EXPORT_VAR=export
[email protected]
:~/work/test/linuxshell$ source test.sh Print Bash Path:/bin/bash export local [email protected]:~/work/test/linuxshell$ . test.sh Print Bash Path:/bin/bash export local

bash + shell script

使用這種型別的命令,是會顯式的呼叫bash shell作為我們的指令碼直譯器進行執行,bash需要存在於我們PATH環境變數裡。

[email protected]:~/work/test/linuxshell$ bash test.sh 
Print Bash Path:/bin/bash
export

[email protected]:~/work/test/linuxshell$ which bash
/bin/bash

當然除了bash,加入我們用於其他型別的shell直譯器,也可以使用同樣的方法執行指令碼。從上面的測試來看,bash + shell script的方式,並不會整合所有的父shell環境變數,但是會繼承父shell export出來的環境變數。

./ + shell script

./這個方法在linux世界是用來執行一切可執行檔案的方法,不僅僅可以用來執行shell指令碼。需要特別注意的是 ./ 並不等於 . 符號,兩者是具有本質區別的。
./ 這個符號後面需要跟一個可執行檔案的路徑,用於定位執行檔案的位置,這個路徑可以是相對路徑。那麼如何區分不同的可執行檔案呢?對於shell指令碼來說,我們會在開頭加上:

#! /bin/bash

這個就代表著這是一個需要使用bash shell來進行解釋的指令碼,當然同樣的方式也適用於其他語言,比如python:

#!/bin/python

這裡的#!是具有異常魔力的標誌,我們叫他magic number。它是用來區分不同型別可執行檔案的一種方式。注意#!後面必須要加上對應的直譯器路徑,並且必須是正確的路徑。否則可能會執行失敗。

擴充套件

當然還有一種情況,假如我的系統安裝了不同型別shell,那麼要如何執行我的指令碼使用不同shell來執行呢?實際上指令碼中的magic number後指定的只是該指令碼預設的執行shell,當我們使用 ./ 來執行時,就會使用預設的shell。如果此時使用顯式的方式,那麼是會覆蓋預設直譯器的。
比如我們在指令碼中第一行使用mksh作為直譯器:

#! /bin/mksh

但是在執行是使用如下命令:

bash test.sh

那麼該指令碼使用bash shell來執行。
比如我的例子:

[email protected]:~/work/test/linuxshell$ ./test.sh 
bash: ./test.sh: /bin/mksh: 直譯器錯誤: 沒有那個檔案或目錄
[email protected]:~/work/test/linuxshell$ bash test.sh
Print Bash Path:/bin/bash
export

由於我的機器沒有按照mksh,所以預設查詢mksh會失敗報錯。但是顯式告訴系統使用bash來執行,就可以執行成功。