Bash

調試零星的 141 shell 腳本錯誤

  • April 15, 2020

在 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[@]}.


該行為是預期的。使用 subshel​​l 代替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

引用自:https://unix.stackexchange.com/questions/580117