Depurando erros esporádicos de script de shell 141

Depurando erros esporádicos de script de shell 141

Ao executar um script no CI (Gitlab, contêiner Docker executando Alpine Linux), estou recebendo falhas esporádicas com o sinal 141 que parece indicar um "SIGPIPE". Mas não entendo qual etapa está falhando ou o que fazer para depurá-la.

  #!/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 ))

O erro esporádico parece acontecer dentro do pipe na penúltima linha, o log que recebo é:

++ git tag
++ cut -d- -f3
++ sort -nr
++ grep -E 'prod-release-(\d+)'
++ head -1
+ RELEASE=323
ERROR: Job failed: exit code 141

Como eu faria para depurar isso para descobrir qual linha realmente falhou? Parece que a variável RELEASE foi preenchida com sucesso, mas de alguma forma ainda explodiu?

Responder1

Depois de head -1fazer seu trabalho, ele sai independentemente de sort -nrter conseguido gravar todos os dados no pipe. Se sorttiver algo mais para escrever e headnão existir mais então sortconseguirá SIGPIPE.

Nada explode. É assim que funcionam os canos. Ao usar headem um pipe, você não deve se surpreender se o comando anterior for encerrado por causa de SIGPIPE.


Teste simples com yesem vez de sort:

$ set -o pipefail
$ yes | head -n 1
y
$ printf '%s\n' "$?" "${PIPESTATUS[@]}"
141             <- overall exit status
141             <- from `yes'
0               <- from `head'

O status de saída é 141e vem de yes.

Isso mostra como depurar: examinando arquivos ${PIPESTATUS[@]}.


O comportamento é esperado. Use um subshell em vez de yes(ou no seu caso, em vez de sort) para manipular o status de saída desta parte do tubo. Exemplo:

$ set -o pipefail
$ (yes; true) | head -n 1
y
$ printf '%s\n' "$?" "${PIPESTATUS[@]}"
0
0
0

Lógica mais complexa para suprimir apenas 141:

(yes; e="$?"; [ "$e" -eq 141 ] && exit 0; exit "$e") | head -n 1

informação relacionada