
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