關於帶有重定向和/或管道的內置命令的行為的 POSIX 規範是什麼?
考慮以下命令:
exit > /dev/null exit | cat
在一些 shell(ksh、bash、(d)ash)上,行為是相同的:第一個命令導致 shell 立即退出,而第二個命令沒有可見行為。
我得出的結論是,第一個命令不涉及 fork(2),而第二個命令涉及兩個(一個執行
exit
,另一個 execve(2) 執行cat
)。我查看了 POSIX 規範第 2.14 節,但沒有找到任何明確說明這一點的內容。
POSIX 是否指定某些命令不能 fork(2) 而其他一些命令必須?是否為標準可接受的第一個命令生成子 shell?
我知道
( exit )
永遠不應該退出目前的 shell,因為括號會產生一個實際執行exit
命令的子 shell,這意味著子 shell 將立即退出。但是,我不確定重定向和管道,因為這裡沒有括號。我問這個問題是因為在最近的課程實驗室中,我們被告知要實現一個最小的 Unix shell。我們可以實現許多“可選功能”,以獲取更多資訊。這些“可選功能”之一是組合重定向和流水線。我們有一些不同的實現,我相信有些實現比其他的更接近 POSIX 的指定行為,因此我想知道實際行為是如何指定的。
好吧(退出),
exit實用程序應使 shell從其目前執行環境中退出
$$ … $$
以及(2.12. Shell 執行環境)
應創建一個子外殼環境作為外殼環境的副本,
$$ … $$此外,多命令管道的****每個命令 都在子shell環境中;然而,作為擴展,管道中的任何或所有命令都可以在目前環境中執行。所有其他命令都應在****目前 shell 環境中執行。
因此
exit
,管道中的管道在其自己的執行環境/子外殼中執行,並且僅退出該管道,而簡單命令中的管道執行在exit > /dev/null
主外殼環境中。(如評論中所述,重定向根本不會影響它。)請注意,第二個引號中間的部分意味著某些 shell 可能會在主環境中執行管道的所有命令,因此即使在這種情況下也會退出整個 shell。在實踐中,這更常見於管道的最後一個命令。
在 Bash 中
lastpipe
,例如:$ bash -c 'true | exit; echo end.' end.
但
$ bash -O lastpipe -c 'true | exit; echo end.'
不列印任何東西。