Debuggen sporadischer 141 Shell-Skriptfehler

Debuggen sporadischer 141 Shell-Skriptfehler

Während ich ein Skript auf CI (Gitlab, Docker-Container mit Alpine Linux) ausführe, treten sporadisch Fehler mit dem Signal 141 auf, das auf ein „SIGPIPE“ hinzuweisen scheint. Aber ich verstehe nicht, welcher Schritt fehlschlägt oder was ich zum Debuggen tun soll.

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

Der sporadische Fehler scheint innerhalb der Pipe in der vorletzten Zeile aufzutreten. Das Protokoll, das ich erhalte, lautet:

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

Wie gehe ich beim Debuggen vor, um herauszufinden, welche Zeile tatsächlich fehlgeschlagen ist? Es sieht so aus, als ob die Variable RELEASE erfolgreich gefüllt wurde, aber dann trotzdem irgendwie abgestürzt ist?

Antwort1

Nachdem head -1es seine Aufgabe erledigt hat, wird es beendet, unabhängig davon, ob sort -nres gelungen ist, alle Daten in die Pipe zu schreiben. Wenn sortnoch etwas zu schreiben ist und headnichts mehr vorhanden ist, sortwird es abgerufen SIGPIPE.

Nichts explodiert. So funktionieren Pipes. Wenn Sie headin einer Pipe verwenden, sollten Sie nicht überrascht sein, wenn der vorhergehende Befehl aufgrund von beendet wird SIGPIPE.


Einfacher Test mit yesstatt sort:

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

Der Exit-Status ist 141und kommt von yes.

Dies zeigt, wie man debuggt: durch Untersuchen ${PIPESTATUS[@]}.


Das Verhalten entspricht dem erwarteten Verhalten. Verwenden Sie eine Subshell anstelle von yes(oder in Ihrem Fall anstelle von sort), um den Beendigungsstatus dieses Teils der Pipe zu manipulieren. Beispiel:

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

Komplexere Logik, um nur Folgendes zu unterdrücken 141:

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

verwandte Informationen