Shell 是使用者與核心對話的介面,也是強大的程式語言環境。本文從終端機與 Shell 關係切入,層層剖析父子 Shell 進程模型、啟動配置檔讀取順序、三類變數作用域、export 機制與跨進程傳值實戰。
tty、終端機模擬器 GNOME Terminal、iTerm2)/bin/bash、/bin/zsh、/bin/fish)echo $SHELL)# 終端機啟動 → 父 Shell (PID 1234)
$ bash script.sh
# 父 Shell fork → 子 Shell (PID 5678) 執行腳本
# 子 Shell 結束 → 回到父 Shell
fork() 建立,複製父進程記憶體空間#!/bin/bash 指定解釋器bash 也會建立子 Shell/etc/profile → 系統級,登入 Shell 讀取/etc/profile.d/*.sh → 模組化系統設定~/.bash_profile | ~/.bash_login | ~/.profile → 使用者級,依序尋找**第一個存在**者讀取~/.bashrc → 互動式 Shell 每次啟動讀取/etc/bashrc → 系統級互動式設定(由 ~/.bashrc 內部 source)最佳實踐:在 ~/.bash_profile 加入 [[ -f ~/.bashrc ]] && source ~/.bashrc,統一配置入口。
| 類型 | 範例 | 定義/修改 | 子 Shell 可見 | 持久性 |
|---|---|---|---|---|
| 內部變數 | $# $0 $? $$ | Shell 內建,唯讀 | ❌ | 進程存續期間 |
| 環境變數 | PATH HOME SHELL PS1 | export VAR=val | ✅ 複本 | 登出失效,除非寫入配置檔 |
| 本地變數 | STR="Hi" | VAR=val | ❌ | 當前 Shell 存續期間 |
STR="Hello World"
./child.sh # 子 Shell 看不到
export STR
./child.sh # 子 Shell 可見
# 永久生效
echo 'export STR="Hello World"' >> ~/.bashrc
# 父 Shell
export STR="Parent"
./child.sh
# child.sh 內容:
echo "Child sees: $STR"
STR="Child modified"
echo "Child now: $STR"
# 結果:
# Child sees: Parent
# Child now: Child modified
# 父 Shell echo $STR → Parent(未被修改)
子進程修改的是**副本**,不影響父進程。
# child.sh
RESULT="computed_value"
echo "$RESULT" > /tmp/child_result_$$
# 父 Shell
./child.sh
RESULT=$(cat /tmp/child_result_$$)
rm /tmp/child_result_$$
| 指令 | 功能 |
|---|---|
set | 顯示所有本地+環境變數 |
unset VAR | 刪除變數 |
export VAR | 設定/升級環境變數 |
env | 顯示環境變數 / 清空環境執行指令 |
declare -x VAR | 同 export |
readonly VAR | 唯讀變數 |
Shell 變數作用域鐵律:環境變數單向流動(父→子副本),本地變數不出閘,子進程無法反向修改父進程。將此圖譜內化,腳本除錯不再迷路。