Linux Shell 中的管道 (|) 是連接程式輸入輸出的強大機制,但當接收端程式提前關閉管道時,發送端會收到 SIGPIPE 信號 (信號 13) 導致「Broken pipe」錯誤。本文深入剖析此現象成因,並提供多種規避策略。
svn log | head$ svn log | head
----------------
r137 | Fwolf | 2007-05-28 13:38:47 +0800 (Mon, 28 May 2007) | 4 lines
更新記錄。
svn: Write error: Broken pipe
head 只需前 10 行,讀完即關閉標準輸入,管道讀端關閉導致寫端 (svn) 收到 SIGPIPE,預設動作為終止進程並輸出錯誤。
find ... | xargs ... | head$ find . -name "*rc" | xargs -i cat {} | head -1
[Desktop]
xargs: cat: terminated by signal 13
xargs 偵測到子進程 cat 因信號 13 (SIGPIPE) 終止,便停止迴圈並報錯。
ulimit 而定)。xargs 會嚴格檢查子進程狀態。將 head 直接作用於檔案,而非管道流:
# 單一檔案
cat file | head -1 # cat 仍會收到 SIGPIPE,但 Bash 不報錯
# 多檔案遍歷:使用 for 迴圈忽略錯誤
for file in .*rc; do cat "$file" | head -1; done
# 最佳寫法:head 直接接受多檔案參數
head -n1 .*rc
# 結合 find:xargs 傳遞檔名給 head
find . -name "*rc" | xargs -i head -n1 {}
優點:消除管道寫入端錯誤,語意清晰。缺點:不適用於需串流處理的大數據場景。
若開發自己的管道工具,可在程式碼中處理:
# C 語言範例
signal(SIGPIPE, SIG_IGN); // 忽略信號,write 返回 EPIPE 錯誤碼
# Python 範例
import signal
signal.signal(signal.SIGPIPE, signal.SIG_DFL) # 恢復預設行為,或自訂處理器
trap 捕捉信號 (Shell 腳本層面)trap '' PIPE # 忽略 SIGPIPE
command1 | command2
trap - PIPE # 恢復預設
head, grep -m) 直接處理檔案參數,避免管道中斷。EPIPE 錯誤 (檢查 write() 返回值),而非依賴信號終止。-r (無輸入不執行) 與 -P (並行) 時,務必確保下游命令不會提前關閉輸入。「Broken pipe」本質是 Unix 哲學「一切皆檔案」下的正常通訊機制,而非錯誤。理解 SIGPIPE 機制,善用檔案參數替代管道,能編寫更健壯的 Shell 命令與腳本。
Apache 核心監控模組 mod_status 與 mod_info 完整配置指南
Nagios 網卡流量監控超時故障排查:SNMP 服務異常導致 CHECK_NRPE Socket Timeout
Linux 系統透過 SSH 管理 VPS 完整指南:金鑰認證、代理穿透、多會話復用與安全加固
Linux 網路硬體配置全攻略:核心模組、乙太網卡、PLIP 與撥號連線
Linux LVS/ipvsadm 實現 Web 負載均衡全實戰:NAT 模式部署與多後端同步方案
Linux 交叉編譯 tslib-1.4 錯誤排除:autoreconf 缺失與 rpl_malloc 未定義完整解決