지속적인 통합을 위해 쉘 스크립트에서 명령을 호출하고 싶습니다. 종료 상태 0은 성공을 나타내고, 그렇지 않으면 실패합니다. 여러 명령을 실행하고 명령 중 하나에 오류가 발생하면 실패하도록 래퍼 스크립트를 작성 중입니다.
그러나 명령 중 하나(타사 소프트웨어)는 실패 시 "사실상" 종료 상태 != 1을 따르지 않습니다. 그러나 실패가 발생하면 stderr에 오류를 인쇄합니다.
현재 래퍼 스크립트는 둘 다 제대로 작동하는 경우 스위치 로 mycommand
인해 종료 상태로 인해 실패합니다 ! = 0:other-command
-e
#!/bin/bash -ex
mycommand --some-argument /some/path/to/file
other-command --other-argument /some/other/file
stderr에 인쇄된 항목이 있는지 어떻게 확인할 수 있나요(주 스크립트 실패 원인)? 내가 시도한 것은 다음과 같습니다.
- stderr 출력이 파일로 리디렉션되고 파일 내용이 검사됩니다.
임시 파일 생성을 피하고 싶습니다. 예를 들어, stderr를 서브쉘 stdin으로 리디렉션합니다.
mycommand 2> >(if grep .; then echo NOK; else echo OK; fi)
이것은 잘 작동하는 것 같지만 여기서는 메인 쉘 종료를 제어할 수 없습니다. 즉,
exit 1
메인 프로그램을 종료하지 않습니다. 또한 결과를 전파하기 위해 서브셸 외부의 변수를 제어할 수 없습니다. 정말 명명된 파이프 같은 것을 만들어야 합니까?추가 파일 설명자를 설정합니다.이 답변.
제가 보기엔 그다지 우아해 보이지는 않네요.
일부 "요구 사항":
- stdout의 일반 출력(역시 출력)에서는 실패하지 않아야 합니다.
- 표준 출력에 다른 유용한 출력을 유지하고 싶습니다.
- 나는 현재 stderr에 인쇄된 모든 출력을 유지하고 싶습니다(stdout일 수 있지만 숨겨서는 안 됩니다).
따라서 래퍼처럼 동작해야 하며, 부정한 상태로만 종료하고 인쇄물을 유지해야 합니다.
stderr에서 무엇이든 확인할 수 있는 좀 더 우아한 기능이 있었으면 좋겠습니다. 모욕은 허용됩니다.
답변1
다음과 같이 할 수 있습니다(POSIXly).
if { cmd 2>&1 >&3 3>&- | grep '^' >&2; } 3>&1; then
echo there was some output on stderr
fi
또는 원래 종료 상태를 유지합니다(0이 아닌 경우).
fail_if_stderr() (
rc=$({
("$@" 2>&1 >&3 3>&- 4>&-; echo "$?" >&4) |
grep '^' >&2 3>&- 4>&-
} 4>&1)
err=$?
[ "$rc" -eq 0 ] || exit "$rc"
[ "$err" -ne 0 ] || exit 125
) 3>&1
125
명령이 0 종료 상태를 반환하지만 일부 오류 출력을 생성하는 상황에는 종료 코드를 사용합니다.
다음과 같이 사용됩니다:
fail_if_stderr cmd its args || echo "Failed with $?"
답변2
# output "NOK" if standard error has any output; "OK" otherwise:
errlog=$(mktemp)
somecommand 1>> "$stdlog" 2> "$errlog"
if [[ -s "$errlog" ]]; then
# File exists and has a size greater than zero
echo "NOK"
else
echo "OK"
fi
# Done parsing standard error; tack it to the regular log
cat "$errlog" >> "$stdlog"
rm -f "$errlog"
답변3
가장 많은 표를 얻은 답변대부분의 경우에 작동합니다. 하지만 set +o errexit
bash에서 사용하고 있기 때문에 오류가 발생합니다. 이것은 bash에서 더 잘 작동합니다.
fail_if_stderr() (
# save current options
bash_options="${-}"
# disable exit on error
set +o errexit
# Save return code of command in rc
rc=$({
("$@" 2>&1 >&3 3>&- 4>&-; echo "$?" >&4) |
grep '^' >&2 3>&- 4>&-
} 4>&1)
# Save return code of grep in err_in_stderr
err_in_stderr=$?
# enable exit on error if it was previously enabled
test "${bash_options#*e*}" != "$bash_options" && set -o errexit
# exit with original return code if it's not zero
[ "$rc" -eq 0 ] || exit "$rc"
# exit with return code 125 if something was in stderr
[ "$err_in_stderr" -ne 0 ] || exit 125
) 3>&1