다음 스크립트에는 구문 오류 또는 일종의 오류가 있습니다.
#!/usr/bin/env bash
set -euo pipefail
if [ ! -f /custom.log]; then
echo "test"
fi
abcxyz
스크립트는 다음과 같은 출력으로 실패합니다.
./test.sh: line 4: [: missing `]'
./test.sh: line 7: abcxyz: command not found
이 스크립트를 어떻게 수정해야 할지 걱정되지 않습니다. 하지만 이 오류가 발생하면 스크립트가 더 이상 진행되지 않도록 하려면 어떻게 해야 합니까? 나는 이 행동을 시행할 것이라고 생각했을 것입니다 set -e
.
답변1
set -e
if
// while
구문 의 조건 섹션 이나 until
a 왼쪽 또는 해당 조건에서 호출되는 함수, 서브셸, 소스 파일, ed 코드와 같은 조건으로 사용되는 실패한 명령에서는 트리거되지 않습니다 .||
&&
eval
그렇다면 다음을 수행하십시오.
if [ ! -f /custom.log ]; then
/custom.log
일반 파일인 경우 스크립트를 종료하면 [
0이 아닌 종료 상태로 종료됩니다.
셸(및 대부분의 다른 구현) [
의 내장 명령은 테스트 된 조건이 충족되지 않거나 구문 오류(예를 들어 모든 구문 오류가 아닌 경우 )가 있는 경우 상태로 종료됩니다.bash
1
2
[ -v 'a[+]' ]
POSIX에서는 오류가 발생한 경우 종료 상태가 1보다 커야 합니다..
따라서 명령이 조건에서 사용되는지 여부에 관계없이 1보다 큰 코드로 명령이 종료되면 스크립트를 종료하도록 선택할 수 있습니다.
shopt -s extdebug # make sure the DEBUG trap propagates to subshells
trap '(($?>1 && (ret=$?))) && exit "$ret"' DEBUG
[ -f / ] || echo / not a regular file # OK
[ -f /] || echo was a syntax error # causes an exit, not output
echo not reached
트랩은 에 의해 종료를 트리거하는 조건과 동일한 조건에서만 실행되므로 ERR
트랩을 사용할 수 없습니다 .ERR
set -e
이제 그 의미에 주의하십시오. 예를 들어 다음과 같은 결과가 발생합니다.
if grep -qs pattern /file; then
echo pattern was found in /file
fi
/file
존재하지 않거나 읽을 수 없는 경우 종료하려면 grep
2 상태로 반환해야 합니다. 를 사용하더라도 -s
해당 사례를 분명히 무시하려는 의도였습니다.
따라서 조건에서 사용하는 명령이 1보다 큰 상태로 종료될 수 있는 조건을 주의해야 합니다. 이러한 문제를 해결하려면 다음과 같은 것이 필요합니다.
if sh -c 'grep -sq pattern / file || exit 1'; then...
다음을 제한할 수 있습니다.종료 상태가 1보다 크면 종료됩니다.[
다음과 같은 명령을 사용하여 or 명령 에 test
:
unset -v previous_BASH_COMMAND
trap '
case $previous_BASH_COMMAND in
("[ "* | "test "*) (($?>1 && (ret=$?))) && exit "$ret"
esac
previous_BASH_COMMAND=$BASH_COMMAND' DEBUG
여기에는 몇 가지 제한 사항이 있습니다. ~ 안에
echo x
([ -f/]; echo y)
그러면 하위 쉘이 종료되지만 $previous_BASH_COMMAND
거기에 설정되지 않았기 때문에 상위 쉘은 종료되지 않습니다. 그리고:
[ -f / ] && echo a regular file
(grep -qs foo /file && echo foo in /file)
echo here
쉘 은 2이고 was 이기 echo here
때문에 실행 시 종료됩니다 .$?
$previous_BASH_COMMAND
[ -f / ]
어쨌든 다음과 같은 것들은
[ -f /] | cat
export var="$([ -f /])"
pipefail
종료 상태가 상위 셸 프로세스에 전파되지 않으므로 감지할 수 없습니다( 첫 번째 경우의 옵션 제외 ).
이제 개발 시(스크립트를 작성하고 테스트할 때) 오류를 쉽게 감지할 수 있는 런타임에 이런 종류의 (취약한) 감지를 추가하는 데 어려움을 겪을 가치가 있는지 잘 모르겠습니다.