Отладка спорадических ошибок 141 скрипта оболочки

Отладка спорадических ошибок 141 скрипта оболочки

При запуске скрипта на CI (Gitlab, Docker-контейнер с Alpine Linux) я получаю спорадические сбои с сигналом 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 была успешно заполнена, но затем каким-то образом все равно сработало?

решение1

После того, 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[@]}.


Поведение ожидаемое. Используйте подоболочку вместо 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

Связанный контент