Bash

怎麼會是真的;做迴聲y;完成 |true會自行消亡,但while true;做迴聲 y |貓;完成 |不是嗎?

  • April 15, 2020

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

也可能相關,

while true; do echo y; done

當我這樣做時會立即死去^C,但是會殺人

while true; do echo y | cat; done

經常需要打^C不止一次。有時一次有效,有時2或3次有效,有時我需要堅持^C一段時間讓它死掉。

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

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

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

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 殺死。

引用自:https://unix.stackexchange.com/questions/580293