가끔 발생하는 141 셸 스크립트 오류 디버깅

가끔 발생하는 141 셸 스크립트 오류 디버깅

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 변수를 성공적으로 채운 것처럼 보이지만 여전히 문제가 발생합니까?

답변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(또는 귀하의 경우에는 대신 ) subshell을 사용하십시오. 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

관련 정보