2011-05-08 30 views
6

當前shell是Will()構造會始終啓動一個子shell?

$ echo $$ 
23173 

注PS的父母是當前shell

$ (ps -o pid,ppid,cmd) 
    PID PPID CMD 
8952 23173 ps -o pid,ppid,cmd 
23173 23169 bash 

但在這裏,PS的父是子shell(bash)的

$ (echo hello ; ps -o pid,ppid,cmd) 
hello 
    PID PPID CMD 
8953 23173 bash 
8954 8953 ps -o pid,ppid,cmd 
23173 23169 bash 

是bash的做優化?在第三種情況下,額外的回聲是如何產生差異並衍生出子殼體的?

+1

熱門技巧:你可以使用'ps -H'來獲得一個進程樹,使它看起來更清楚一點,而無需自己連接PID和PPID。 (儘管這並沒有改變潛在的問題 - 它只是使其更容易看到)。 – 2011-05-08 16:31:38

+1

要做更好的分析,首選$ BASHPID優於$$ – sehe 2011-05-08 20:45:19

+0

請注意,如果您想要在沒有子shell的情況下進行分組,請使用'{brackets ; }'。儘管它們需要一些額外的語法(空格,分號)。 – 2011-05-09 13:11:24

回答

6

是的,你所看到的是一種優化。從技術上講,(…)構造總是按照定義啓動子shell。大多數情況下,子shell在單獨的子進程中運行。這可確保子外殼中的所有內容都保留在子外殼中。如果bash可以保證這個隔離屬性,那麼可以自由使用它喜歡的任何實現技術。

在片段(ps -o pid,ppid,cmd)中,顯然沒有任何東西可以影響父shell,所以在bash中有一個優化,使得它不會爲子shell分離一個單獨的進程。片段(echo hello ; ps -o pid,ppid,cmd)對於優化器來說太複雜以至於無法識別不需要子shell。

如果您使用ksh進行實驗,您會注意到它的優化器更具侵略性。例如,它不會爲(echo hello ; ps -o pid,ppid,cmd)分叉子流程。

+0

您是否在bash impl代碼中提供了關於優化程序如何放棄的鏈接?我發現類似的行爲[沒有](https://unix.stackexchange.com/q/401020/212862)'(...)'語法。另外[與](https://stackoverflow.com/q/46860926/5771861)'{...; '語法。有時中間子外殼可以避免,但是當這種情況聽起來像實現依賴於我。或者,是否正式記錄了優化行爲? – 2017-10-28 19:07:02

+0

@Hakan看看源代碼。它沒有記錄,因版本而異。 – Gilles 2017-10-28 19:10:08

1

可以通過簡單地「執行」該命令來實現由單個簡單命令而不是多個命令的列表或管道組成的子shell,即用所調用的命令的進程替換子shell。如果子shell更復雜,那麼簡單的exec是不可能的,subshel​​l必須留待管理命令序列。

從您的診斷中,不可能區分bash優化和bool優化之間的區別,其中由簡單命令組成的子shell被優化爲被調用命令的「直接」分支和執行程序,該命令被調用。這並不令人驚訝,因爲差異幾乎是完全學術的。

相關問題