在運行shell腳本時候,有三種方式來調用外部的腳本,exec(exec script.sh)方式、source(source script.sh)方式、fork(./script.sh)方式。
fork方式
通常情況下在系統中通過相對路徑或絕對路徑執行一個命令時,都會由父進程開啓一個子進程,當子進程結束後再返回父進程,這種行爲過程就叫fork。當腳本中正常調用一個外部命令或其他腳本時,都會fork一個子shell進程,我們的命令會運行在這個子shell中。
subshell.sh
#!/bin/bash
#使用&在後臺進程開啓子shell
count=0
for i in {1..254}
do
ping -c1 -i0.2 -WL 192.168.43.$i >/dev/null && let count++ &
done
echo $count
for_test.sh
#!/bin/bash
sleep 5
#絕對路徑或相對路徑調用外部腳本時會fork子進程
/home/minger/share/shell/subshell.sh
這個腳本在執行的過程中會打開一個終端窗口,反覆執行pstree可以獲得如下的進程樹信息。可以看出,我們腳本調用一個外部命令時(sleep)時,系統會fork一個子shell,sleep命令是在子shell中執行的。
當腳本通過相對路徑或者絕對路徑調用外部其他腳本時,會fork一個子進程,並且subshell.sh腳本中命令被觸發執行時也會再次fork子進程。
可以用pstree查看:
使用fork方式開啓的子進程是父進程的一個副本,因此會自動單向繼承父進程的環境,如環境變量、資源權限、內存中的數據、信號等等。但是,父進程無法繼承子進程環境。
exec方式
使用exec方式調用其他命令或腳本時,系統不會開啓子進程,而是使用新的程序替換當前的shell環境,因爲當前shell被替換了,所以當exec調用的程序結束後,當前環境會被關閉。
exec執行命令流程圖:
上面的圖中,通過exec時執行ls命令,一個是使用用echo命令讓屏幕回顯一個字符串信息,最後一個是cd 命令,用於切換目錄。但是,第一命令使用exec調用ls,系統使用ls命令替換當前的腳本,整個進程就變成了一個ls命令,當ls命令結束後進程也就結束了。
下面來看看例子:
#!/bin/bash
exec ls
echo "test"
cd /shell
這裏有個特例,當exec後面的參數文件重定向時,不會替換當前的shell環境,腳本後續其他命令也不會受到任何影響。
source方式
使用source或者“.”來調用外部腳本,不會產生新的進程,繼承當前shell環境變量,而且被調用的腳本運行結束後,它擁有的環境變量和聲明變量會被當前shell保留,類似將調用腳本的內容複製過來直接執行。執行完畢後原主shell繼續運行。
下面來看個簡單例子:
tmp.sh
#!/bin/bash
env="Minger"
source.sh
#!/bin/bash
source /tmp/tmp.sh
echo "hi,$env"
ls /
在上面的source.sh腳本中使用source命令加載/tmp/tmp.sh腳本,source命令會在不開啓shell情況下,將tmp.sh中的所有命令加載當前shell環境中,類似tmp.sh文件中的所有命令編寫在source.sh文件中的一樣。
歡迎關注公衆號【程序猿編碼】,添加本人微信號(17865354792),回覆:領取學習資料。或者回復:進入技術交流羣。網盤資料有如下: