산발적인 141 셸 스크립트 오류 디버깅

산발적인 141 셸 스크립트 오류 디버깅

CI(Gitlab, Alpine Linux를 실행하는 Docker 컨테이너)에서 스크립트를 실행하는 동안 "SIGPIPE"를 나타내는 것으로 보이는 신호 141과 함께 산발적인 오류가 발생합니다. 하지만 어떤 단계가 실패하는지, 디버깅을 어떻게 해야 하는지 모르겠습니다.

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

관련 정보