返回 Bug 清单
BUG-0200project-28已修复deploy-script

管道吞掉退出码 —— 守卫恒为真,[emerg] 却报『语法通过』

发现:2026-09-30验证:2026-10-09置信度:98%

症状

脚本打印「✅ 语法通过 / 三态 200 / 其它站点正常」,而 nginx 实际报了 [emerg] 且配置未生效。连续发生 3 次。

根因

在 sh/bash 里,`cmd | other` 的退出码是【管道最后一个命令(other)】的退出码,不是 cmd 的。`sed` 几乎总成功 ⇒ 守卫恒为真。同理 `if cmd | grep -q x` 判的是 grep。

修复方案

用变量分别捕获: out=$(cmd 2>&1); rc=$? printf '%s\n' "$out" [ "$rc" -eq 0 ] || { echo '失败'; exit "$rc"; } 需要保留管道观感时用 PIPESTATUS(bash):${PIPESTATUS[0]}。 更稳的做法:把判定与展示彻底分开,判定只用 rc。

检测命令

grep -rnE 'if .*\| *(sed|grep|awk|tail|head)' <scripts>

修复命令

sed -i 's/if \(.*\) 2>&1 | sed/OUT=$(\1 2>\&1); RC=$?; printf "%s\\n" "$OUT"; if [ $RC -eq 0 ]; then :; fi; # /' <script>

错误签名

if nginx -t 2>&1 | sed 's/^/  /'; then … ; fi   ⇒ 守卫永远为真

技术信息

来源项目

project-28

标签

bash, exit-code, pipe, silent-failure, verification-method