Shell 腳本間相互調用有三種本質不同的方式:source/. 在當前 Shell 環境執行(保留變數、函數、改變當前目錄),sh script 或 ./script 則啟動子 Shell(環境隔離)。本文以實測 PID 與變數傳遞示範三者差異,並補充 exec 替換當前進程的特殊用法。

| 方式 | 指令範例 | 執行環境 | 變數/函數影響 | 典型用途 |
|---|---|---|---|---|
| source | source first.sh. first.sh | 當前 Shell | 子腳本設定的變數、函數、cd 目錄保留於父腳本 | 載入設定檔、函數庫、環境變數 |
| fork (子 Shell) | sh first.sh./first.sh | 新子 Shell | 子腳本環境變更不影響父腳本;父腳本 export 的變數可被子腳本繼承 | 獨立執行任務、隔離環境 |
| exec 替換 | exec ./first.sh | 替換當前進程 | 當前進程被替換,PID 不變,程式碼完全切換 | 啟動器、尾端服務啟動 |
#!/bin/bash
A=B
echo "PID for 1.sh before: $$"
export A
echo "1.sh: \$A is $A"
case $1 in
exec)
echo "using exec..."
exec ./2.sh ;;
source)
echo "using source..."
. ./2.sh ;;
*)
echo "using fork by default..."
./2.sh ;;
esac
echo "PID for 1.sh after: $$"
echo "1.sh: \$A is $A"
#!/bin/bash
echo "PID for 2.sh: $$"
echo "2.sh get \$A=$A from 1.sh"
A=C
export A
echo "2.sh: \$A is $A"
$ ./1.sh # fork 模式
PID for 1.sh before: 5845364
1.sh: $A is B
using fork by default...
PID for 2.sh: 5242940 # PID 不同,子進程
2.sh get $A=B from 1.sh
2.sh: $A is C
PID for 1.sh after: 5845364
1.sh: $A is B # 父腳本 A 未變
$ ./1.sh exec # exec 模式
PID for 1.sh before: 5562668
1.sh: $A is B
using exec...
PID for 2.sh: 5562668 # PID 相同,進程被替換
2.sh get $A=B from 1.sh
2.sh: $A is C
# 1.sh 後續程式碼不再執行
$ ./1.sh source # source 模式
PID for 1.sh before: 5156894
1.sh: $A is B
using source...
PID for 2.sh: 5156894 # PID 相同,同一進程
2.sh get $A=B from 1.sh
2.sh: $A is C
PID for 1.sh after: 5156894
1.sh: $A is C # 父腳本 A 被修改為 C
source config.sh 或 . config.sh./task.shexec /usr/bin/mydaemonphp script.php、python3 script.py 同屬 fork 模式