Bash
調試零星的 141 shell 腳本錯誤
在 CI(Gitlab,執行 Alpine Linux 的 Docker 容器)上執行腳本時,我收到信號 141 的零星故障,這似乎表明“SIGPIPE”。但我不明白哪一步失敗或如何調試它。
#!/usr/bin/env bash set -euxo pipefail set -a # ... git fetch --tags RELEASE=$(git tag | grep -E "${BUILD_ENV}-release-(\d+)" | cut -d"-" -f3 | sort -nr | head -1) RELEASE=$(( RELEASE + 1 ))
零星的錯誤似乎發生在倒數第二行的管道內,我得到的日誌是:
++ git tag ++ cut -d- -f3 ++ sort -nr ++ grep -E 'prod-release-(\d+)' ++ head -1 + RELEASE=323 ERROR: Job failed: exit code 141
我將如何調試它以確定哪條線實際上失敗了?看起來它成功填充了 RELEASE 變數,但不知何故仍然爆炸了?
完成
head -1
其工作後,無論是否sort -nr
設法將所有數據寫入管道,它都會退出。如果sort
有更多的東西要寫並且head
沒有更多的東西,那麼sort
就會得到SIGPIPE
。什麼都不會爆炸。這就是管道的工作原理。當你
head
在管道中使用時,如果前面的命令因為SIGPIPE
.
yes
使用代替的簡單測試sort
:$ set -o pipefail $ yes | head -n 1 y $ printf '%s\n' "$?" "${PIPESTATUS[@]}" 141 <- overall exit status 141 <- from `yes' 0 <- from `head'
退出狀態是
141
,它來自yes
。這顯示瞭如何調試:通過檢查
${PIPESTATUS[@]}
.該行為是預期的。使用 subshell 代替
yes
(或在您的情況下代替sort
)來操作這部分管道的退出狀態。例子:$ set -o pipefail $ (yes; true) | head -n 1 y $ printf '%s\n' "$?" "${PIPESTATUS[@]}" 0 0 0
僅壓制更複雜的邏輯
141
:(yes; e="$?"; [ "$e" -eq 141 ] && exit 0; exit "$e") | head -n 1