script.sh:
#!/bin/bash
my-bin-file-i-run
if [ $? -eq 0 ]
then
exit 0
else
if [[ >&2 == *"name_to_handle_at"* ]]; then
exit 0
fi
echo >&2
exit 1
fi
명령을 실행하고 싶은데 메시지에 "name_to_handle_at" 오류가 발생하면 스크립트에 오류가 없는 것처럼 처리하고 다른 모든 오류는 평소대로 표시됩니다. 실제로 작동시킬 수 없습니다.
답변1
==
이전에 실행된 명령의 표준 오류를 유사한 명령 과 비교할 수 없기 때문에 구문에 문제가 있습니다 .
한 가지 제안은 오류 스트림을 파일에 저장한 다음 파일을 구문 분석하는 것입니다.
#!/bin/bash
if ! my-bin-file-i-run 2>error.log; then
if ! grep -q -F 'name_to_handle_at' error.log; then
echo 'some error message' >&2
exit 1
fi
fi
그러면 명령이 실행되고 표준 오류 스트림이 이라는 디렉터리로 리디렉션됩니다 . error.log
명령이 오류로 종료된 경우 로그 파일에서 문자열을 찾는 grep
데 사용됩니다 . name_to_handle_at
찾지 못하면 오류 메시지가 인쇄되고 스크립트는 0이 아닌 종료 상태로 종료됩니다.
다른 경우에는 스크립트가 종료 상태 0으로 종료됩니다.
error.log
스크립트가 종료될 때 파일을 삭제 하려면 명시적으로 rm error.log
해당 위치에서 또는 트랩을 사용하여 EXIT
삭제할 수 있습니다.
#!/bin/bash
trap 'rm -f error.log' EXIT
if ! my-bin-file-i-run 2>error.log; then
if ! grep -q -F 'name_to_handle_at' error.log; then
echo 'some error message' >&2
exit 1
fi
fi
답변2
프로그램의 stderr을 grep으로 파이프하여 사용할 수 있습니다(배쉬 특정) PIPESTATUS
명령 성공/실패 및 명령 인쇄/오류 메시지 인쇄 안 함의 4가지 조합을 구별하는 변수:
{ your_command 2>&1 >&3 | grep your_error_message >/dev/null; } 3>&1
case ${PIPESTATUS[*]} in
0*) ;; # the command succeeded
*0) ;; # the command failed but printed the error message
esac
예:
# usage wrapper pattern cmd args ...
wrapper(){
msg=$1; shift
{ "$@" 2>&1 >&3 | grep "$msg" >/dev/null; } 3>&1
case ${PIPESTATUS[*]} in
0*|*0) return 0;;
*) return "${PIPESTATUS[0]}";;
esac
}
# usage test_cmd status error_message
test_cmd(){ status=$1; shift; echo >&2 "$@"; return "$status"; }
$ wrapper foo test_cmd 13 foo; echo $?
0
$ wrapper foo test_cmd 13 bar; echo $?
13
노트:
grep >/dev/null
로 바꾸지 마십시오 grep -q
. 그러면 첫 번째 일치에서 grep이 종료되고 명령이 SIGPIPE로 표시됩니다.
그러나 ... | tee /dev/stderr | ...
명령과 grep 사이에 하나를 추가하면 오류 메시지가 grep에 전달되고 stderr에 인쇄됩니다.
많은 저수준 프로그램(특히 Python 스크립트)은 stderr 대신 stdout에 오류 메시지를 기록합니다.
your_command 2>&1 | ...
{ 2>&1 >&3 | ... } >&3
그 fd 저글링 대신 .