
Mientras ejecuto un script en CI (Gitlab, contenedor Docker que ejecuta Alpine Linux), obtengo fallas esporádicas con la señal 141 que parece indicar un "SIGPIPE". Pero no entiendo qué paso falla ni qué hacer para depurarlo.
#!/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 ))
El error esporádico parece ocurrir dentro de la tubería en la penúltima línea, el registro que obtengo es:
++ git tag
++ cut -d- -f3
++ sort -nr
++ grep -E 'prod-release-(\d+)'
++ head -1
+ RELEASE=323
ERROR: Job failed: exit code 141
¿Cómo haría para depurar esto para descubrir qué línea realmente falló? ¿Parece que la variable RELEASE se completó correctamente pero de alguna manera explotó?
Respuesta1
Después de head -1
hacer su trabajo, sale independientemente de si sort -nr
logró escribir todos los datos en la tubería. Si sort
tiene algo más que escribir y head
ya no existe, lo sort
conseguiré SIGPIPE
.
Nada explota. Así funcionan las tuberías. Cuando utilice head
en una tubería, no debería sorprenderse si el comando anterior sale debido a SIGPIPE
.
Prueba simple con yes
en lugar de sort
:
$ set -o pipefail
$ yes | head -n 1
y
$ printf '%s\n' "$?" "${PIPESTATUS[@]}"
141 <- overall exit status
141 <- from `yes'
0 <- from `head'
El estado de salida es 141
y viene de yes
.
Esto muestra cómo depurar: examinando ${PIPESTATUS[@]}
.
El comportamiento es esperado. Utilice una subcapa en lugar de yes
(o en su caso en lugar de sort
) para manipular el estado de salida de esta parte de la tubería. Ejemplo:
$ set -o pipefail
$ (yes; true) | head -n 1
y
$ printf '%s\n' "$?" "${PIPESTATUS[@]}"
0
0
0
Lógica más compleja para suprimir únicamente 141
:
(yes; e="$?"; [ "$e" -eq 141 ] && exit 0; exit "$e") | head -n 1