SIGPIPE 和 bash 管道失敗

SIGPIPE 和 bash 管道失敗

我試圖更好地理解 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退出並破壞管道之前設法寫入所有輸出。這是因為:lshead

  • head閱讀的內容可能比最終印刷的內容多,
  • 無論如何,管道都有一個緩衝區。

SIGPIPE 是透過實際寫入損壞的管道來觸發的。如果在退出ls之前設法寫入所有輸出head,則不會有任何寫入行為觸發 SIGPIPE。

ls可能無法在head退出之前寫入所有輸出。然後它會嘗試寫入更多內容並收到 SIGPIPE。

由於lshead並行運行,我認為一般來說存在競爭條件。可能會發生某些特定輸出ls隨機觸發或不觸發 SIGPIPE 的情況。

嘗試使用yes而不是ls …

{ yes ; echo "$?" 1>&2 ; } | head

或者

( set -o pipefail; { yes ; echo "$?" 1>&2 ; } | head; )

yes產生的輸出不會自行結束,因此head退出後總會有一個觸發 SIGPIPE 的寫入行為。上面的每個指令都會給你141肯定的訊息。

這與 無關pipefail

相關內容