怎麼會“雖然是真的;”回顯 y;完成 | true 會自行消亡,但 while true;迴聲 y |貓;完成 |是的`不是嗎?

怎麼會“雖然是真的;”回顯 y;完成 | true 會自行消亡,但 while true;迴聲 y |貓;完成 |是的`不是嗎?

為了澄清標題問題,我理解前者為什麼會死。我不明白為什麼後者不這樣做,只是為了將 a 添加| cat到循環體中。

也可能相關,

while true; do echo y; done

當我這樣做時立即死亡^C,但殺戮

while true; do echo y | cat; done

經常需要擊打^C不只一次。有時一次有效,有時2或3次有效,然後有時我需要堅持^C一段時間才能死去。

這兩種行為都發生在 bash 和 zsh 中,儘管這種^C行為在 bash 中似乎較少見。

對於這兩種行為,這並不限於將管道添加到cat. | dd| tee等也會導致它們。甚至echo y | true造成它。循環體中似乎存在任何管道。

為什麼循環體中管道的存在會改變循環對訊號的反應?

答案1

在 中while true; do echo y; done | true,由於echo是內建的,因此您有一個子 shell 進程,它y\n在循環中寫入管道。

返回時true,該管道的讀取端被關閉,因此寫入寫入端會導致 aSIGPIPE被傳遞到寫入進程。在這裡,這是運行循環的子 shell 進程。

在 中while true; do echo y | cat; done | true,它cat寫入管道。cat通常不是內建的,即使是內建的,在 zsh 和 ksh 之外的 shell 中,所有管道元件始終在子進程中運行。

因此,這裡只有正在運行的進程cat會死亡,而運行循環的子 shell 進程會繼續運行更多cat進程,這些進程一旦寫入y\n標準輸出就會死亡。

在 ksh93/ksh2020 中,如果您這樣做:

$ builtin cat
$ type cat
cat is a shell builtin
$ set -o pipefail
$ while true; do echo y | cat; done | true; kill -l "$?"
PIPE

這次,cat它是內建的,並且確實在與循環相同的進程中運行(就像cat第一個管道中最右邊的命令一樣,ksh 不會在子 shell 中運行該命令),因此子 shell 會通過管道true退出並kill -l確認它是被 SIGPIPE 殺死。

相關內容