2016-04-21 38 views
4

該shell腳本的行爲與預期相同。管道是否保證在任何POSIX shell中創建子shell?

trap 'echo exit' EXIT 

foo() 
{ 
    exit 
} 

echo begin 
foo 
echo end 

這是輸出。

$ sh foo.sh 
begin 
exit 

這表明腳本在執行foo時退出。

現在看到下面的腳本。

trap 'echo exit' EXIT 

foo() 
{ 
    exit 
} 

echo begin 
foo | cat 
echo end 

這裏唯一的區別是foo的輸出被輸入到cat中。現在輸出如下所示。

begin 
end 
exit 

這表明,在執行foo因爲end被印刷在腳本不退出。

我相信會發生這種情況,因爲在bash中,管道會導致子shell被打開,所以foo | cat等於(foo) | cat

在任何POSIX shell中保證這種行爲?我在http://pubs.opengroup.org/onlinepubs/9699919799/找不到POSIX標準中的任何內容,這意味着管道必須導致子外殼。有人可以確認這種行爲是否可以依賴嗎?

回答

1

2.12 Shell Execution Environment你會發現這句話:

一個子shell環境應創建爲shell環境的副本,除了應設置爲默認的行動,沒有被忽略的信號陷阱。對子shell環境所做的更改不會影響shell環境。命令替換,用圓括號分組的命令和異步列表應在子shell環境中執行。另外,多命令管道的每個命令都在一個子shell環境中;作爲擴展,然而,流水線中的任何或所有命令可以在當前環境中執行。所有其他命令應在當前shell環境中執行。

凡爲這一問題的關鍵句是

此外,多指令管道的每個命令在一個子shell環境;作爲擴展,但是,在管道的任何或所有命令可以在當前的環境

所以不包括擴展名(其bash在管線使用的東西像lastpipe和,我想,用於第一元件執行但顯然不是或者至少不總是),它看起來像你可以認爲管道的每個部分都會有一個子shell,但例外意味着你不能完全依靠這個。

+0

'(foo)'保證在任何POSIX shell的子shell中執行'foo'嗎? –

+0

這就是上面的引用和[複合命令](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_04)似乎向我指出的。我沒有看到有關任何地方的任何例外情況(對於我來說,這似乎很奇怪)。 –