![SIGPIPE 和 bash 管道失敗](https://rvso.com/image/231080/SIGPIPE%20%E5%92%8C%20bash%20%E7%AE%A1%E9%81%93%E5%A4%B1%E6%95%97.png)
我試圖更好地理解 Linux 上的 SIGPIPE。
我運行了這個實驗:{ ls -al /tmp/ ; echo "$?" 1>&2 ; } | head
它迴響了141
我所理解的退出代碼,該退出代碼是給予退出的進程以前SIGPIPE
,我已經做了很多次,但沒有理解SIGPIPE
並且我通常運行的細微差別set -eEuo pipefail
,所以,我試圖理解為什麼我的由於管道損壞,代碼並不是一直失敗...所以我運行了另一個實驗:( set -o pipefail; { ls -al /tmp/ ; echo "$?" 1>&2 ; } | head; )
那一次我在回顯中得到了 0...所以當pipefail
啟用時,這是否意味著它SIGPIPE
被抑制了?還是我誤解了這裡發生的事情?
答案1
ls
即使 的輸出比列印的內容長,也可以在head
退出並破壞管道之前設法寫入所有輸出。這是因為:ls
head
head
閱讀的內容可能比最終印刷的內容多,- 無論如何,管道都有一個緩衝區。
SIGPIPE 是透過實際寫入損壞的管道來觸發的。如果在退出ls
之前設法寫入所有輸出head
,則不會有任何寫入行為觸發 SIGPIPE。
或ls
可能無法在head
退出之前寫入所有輸出。然後它會嘗試寫入更多內容並收到 SIGPIPE。
由於ls
和head
並行運行,我認為一般來說存在競爭條件。可能會發生某些特定輸出ls
隨機觸發或不觸發 SIGPIPE 的情況。
嘗試使用yes
而不是ls …
:
{ yes ; echo "$?" 1>&2 ; } | head
或者
( set -o pipefail; { yes ; echo "$?" 1>&2 ; } | head; )
yes
產生的輸出不會自行結束,因此head
退出後總會有一個觸發 SIGPIPE 的寫入行為。上面的每個指令都會給你141
肯定的訊息。
這與 無關pipefail
。