Subshell
Subshell
Subshell 嘅定義喺一啲書本或者資料中模糊唔清,畀出嘅解釋往往同某啲例子自相矛盾,令人捉摸唔透。 所以,為咗避免呢種語義同邏輯上嘅問題,呢度唔會畀出佢嘅定義(建議參考官方 BASH 手冊), 亦唔會用 “子 Shell” 呢個翻譯,只係從佢嘅實際表現去理解佢嘅定義。 下面列舉嘅變量同 Subshell 概念有密切嘅關係。
Bash Reference Manual
Bash 參考手冊
BASH_SUBSHELL
Shell 變量,非環境變量,官方手冊解釋。
Incremented by one within each subshell or subshell environment when the shell begins executing in that environment. The initial value is 0. If BASH_SUBSHELL is unset, it loses its special properties, even if it is subsequently reset.
亦可以用 man 命令,內容可能會有啲唔同。
man bash | grep -A 3 'BASH_SUBSHELL' | head -n 4
echo $BASH_SUBSHELL
0
SHLVL
環境變量,官方手冊解釋。
Incremented by one each time a new instance of Bash is started. This is intended to be a count of how deeply your Bash shells are nested.
用 man 命令。
man bash | grep 'SHLVL'
呢個值係從 1 開始嘅。
echo $SHLVL
1
命令分組
全稱 Command Grouping,Bash 提供兩種方法創建命令分組。
括號:()
呢個方法會創建一個 Subshell 環境去處理命令分組。
(pwd; echo $BASH_SUBSHELL)
/home/kuga
1
(pwd; (echo $BASH_SUBSHELL))
/home/kuga
2
(pwd; (echo $SHLVL))
1
可以得出以下結論。
- BASH_SUBSHELL:每創建一個 Subshell 就加 1。
- SHLVL:無論創建幾多個 Subshell,都唔變。
花括號:{}
呢個方法唔會創建 Subshell,命令分組係喺當前 Shell 嘅上下文中處理嘅。 喺語法上,花括號同命令之間嘅空格唔可以省略,每個命令結尾嘅分號亦係必須嘅。
{ pwd; { echo $BASH_SUBSHELL; } }
/home/kuga
0
{ pwd; { echo $SHLVL; } }
/home/kuga
1
Shell PID
可以通過 BASHPID 或者 $$
睇 Shell 嘅 PID,但佢哋係有區別嘅。
BASHPID
Shell 變量,非環境變量,官方解釋。
Expands to the process ID of the current Bash process. This differs from $$ under certain circumstances, such as subshells that do not require Bash to be re-initialized. Assignments to BASHPID have no effect. If BASHPID is unset, it loses its special properties, even if it is subsequently reset.
echo $BASHPID
56414
用 ()
睇 BASHPID。
(ps -f --forest; echo $BASHPID)
UID PID PPID C STIME TTY TIME CMD
kuga 56414 56412 0 10:11 pts/0 00:00:00 -bash
kuga 57325 56414 0 15:13 pts/0 00:00:00 \_ -bash
kuga 57326 57325 0 15:13 pts/0 00:00:00 \_ ps -f --forest
57325
可以睇到,BASHPID 輸出咗 Subshell 嘅 PID。
特殊參數 $$
官方解釋。
($$) Expands to the process ID of the shell. In a subshell, it expands to the process ID of the invoking shell, not the subshell.
喺 Subshell 中,$$
表示嘅係 invoking shell 嘅 PID。
(pwd; (ps -f --forest; echo $$))
/home/kuga
UID PID PPID C STIME TTY TIME CMD
kuga 56414 56412 0 10:11 pts/0 00:00:00 -bash
kuga 57347 56414 0 15:20 pts/0 00:00:00 \_ -bash
kuga 57348 57347 0 15:20 pts/0 00:00:00 \_ -bash
kuga 57349 57348 0 15:20 pts/0 00:00:00 \_ ps -f --forest
56414
可以睇到,無論有幾多個 Subshells,$$
始終表示頂層 Bash 嘅 PID。
創建 Bash 實例
喺 Bash 中輸入 bash
就可以創建一個全新嘅 Bash 實例。
bash
ps -f --forest
UID PID PPID C STIME TTY TIME CMD
kuga 56414 56412 0 10:11 pts/0 00:00:00 -bash
kuga 57359 56414 0 15:29 pts/0 00:00:00 \_ bash
kuga 57402 57359 0 15:30 pts/0 00:00:00 \_ ps -f --forest
呢個時候再觀察一下上面提到嘅變量。
echo $BASH_SUBSHELL $SHLVL $BASHPID $$
0 2 57359 57359
- BASH_SUBSHELL:冇變。
- SHLVL:從 1 -> 2。
- BASHPID:新 Bash 實例嘅 PID。
- $$:新 Bash 實例嘅 PID。
如果話呢種創建 Bash 嘅方式都係 Subshell 嘅話,語義同表現上就會自相矛盾。