개별 명령에 대해 set -e를 비활성화하는 방법은 무엇입니까?


36

set -e 명령은 명령이 0이 아닌 종료 코드를 리턴 할 때 bash 스크립트가 즉시 실패하게합니다.

  1. 스크립트 내에서 개별 명령에 대해이 동작을 사용하지 않는 쉽고 우아한 방법이 있습니까?

  2. 이 기능은 Bash Reference Manual ( http://www.gnu.org/software/bash/manual/bashref.html )에 어디에 기록되어 있습니까?

답변:


29
  1. 이 같은:

    #!/usr/bin/env bash
    
    set -e
    echo hi
    
    # disable exitting on error temporarily
    set +e
    aoeuidhtn
    echo next line
    
    # bring it back
    set -e
    ao
    
    echo next line

    운영:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
  2. set내장 도움말에 설명되어 있습니다 .

    $ type set
    set is a shell builtin
    $ help set
    (...)
    Using + rather than - causes these flags to be turned off.

https://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin에 동일하게 문서화되어 있습니다 .


감사! 다른 가능성을 찾았습니다 : #! / bin / bash set -e # 다음 줄의 주석 처리를 해제하여 set -e 효과를 확인하십시오. #blubb if blubb; 그런 다음 에코 "명령 blubb는 성공적이었습니다." else echo "명령 blubb 실패. 종료 코드 : $?" fi echo 일반 스크립트 종료
Gustave

22

실수로 보석금을 해제하는 대안은 무엇이든 성공을 거두는 것입니다. 다음과 같이 할 수 있습니다 :

cmd_to_run || true

0을 반환하므로 (-e) set -e가 트리거되지 않아야합니다.


3
faulty_cmd || :이것에 대한 또 다른 인기있는 관용구입니다. (와 :동의어입니다 true).
ulidtko

3
@ulidtko-흥미로운. 이 찾을 토끼 구멍 아래로 나를지도 stackoverflow.com/questions/3224878/...을 진정한 대에서 역사를 얻을 :
어니

12

리턴 / 오류 코드 (기능 또는 포크)를 포착하려고하면 다음과 같이 작동합니다.

function xyz {
    return 2
}

xyz && RC=$? || RC=$?

8

"즉시 쉘 종료 옵션"이 적용되거나 무시되는 경우 실행 된 명령의 컨텍스트에 따라 다릅니다 ( Arkadiusz Drabczyk 덕분에 기본 제공 세트의 Bash 참조 매뉴얼 섹션 참조 ).

특히 명령이 if 문의 테스트의 일부인 경우이 옵션은 무시됩니다. 따라서 다음과 같은 if 문을 사용하여 "즉시 종료 컨텍스트"내에서 명령을 실행하고 성공 또는 실패를 확인할 수 있습니다.

#!/bin/bash

set -e

# Uncomment next line to see set -e effect:
#blubb

if blubb; then
  echo "Command blubb was succesful."
else 
  echo "Command blubb failed. Exit code: $?"
fi
echo "Script exited normally."

"then"문을 생략하고 더 적은 행을 사용할 수 있습니다.

if blubb; then :;
else echo "Command blubb failed. Exit code: $?"; fi

2

또 다른 접근 방식은 상당히 간단하며 (및 set이외에 다른 옵션 에도 적용됨 -e) :

$-설정을 복원 하는 데 사용하십시오 .

예를 들면 다음과 같습니다.

oldopt=$-
set +e
# now '-e' is definitely disabled.
# do some stuff...

# Restore things back to how they were
set -$oldopt

대한 있지만 -e특히, 옵션 다른 사람이 (mentined 한 || true또는 "내부 넣어 if") 더 관용적 일 수 있습니다.


0

실제로 최근에 비슷한 질문이 있었지만 (게시하지는 않았지만), 내가 볼 수 있듯이 명령 전에 set + e를 사용하고 나중에 set -e를 사용하면 가장 우아하게 작동합니다. 다음은 명령의 응답을 잡아서 오류가 발생하지 않도록하는 예입니다.

#!/bin/sh

args=""
for argcol in $*
do
    args="${args} ${argcol}"
done
fortunevar=""
fortfail=""
{
    set +e
    fortunevar=`fortune $args`
    fortfail=$?
    set -e
} &> /dev/null
if [ $fortfail == 0 ]
then
    echo ${fortunevar}
    say ${fortunevar}
else
    echo misfortune: an illegal option was detected!
    echo misfortune: usage: misfortune [-afilosw] [-m pattern][ [#%] file/directory/all]
fi

이것은 '포춘'의 출력을 잡고 종료 상태를 확인하고 반향하여 알려줍니다. 나는 이것이 당신이 요구 한 것이거나 적어도 비슷한 것이라고 생각합니까? 어쨌든 이것이 도움이되기를 바랍니다.


분명히 말하면, 괄호 안의 비트가 / dev / null로 리디렉션되는 것은 당신이 따르는 것입니다. 명령을 출력하지 않고 프로그램을 종료하지 않고 오류 상태를 확인합니다.
애디슨 크럼프

0

일시적으로 무언가를 바꾸고 싶다면 서브 쉘을 시작하고 싶습니다. 아래 명령은 첫 번째 bad_command가 무시되고 두 번째는 실행을 중단 함을 보여줍니다.

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.