2017-11-26 1 views
1

내 CI에서 실행되며 물리적 MacOS 및 여러 도커 Linux 이미지에서 코드를 실행하려고하는 다음 bash 스크립트가 있습니다.명령문 중 하나가 오류 코드를 반환하는 경우 Bash - break 조건절!

테스트가 ( run_test1 또는 run_test2을) 실패하면 그들이 오류 코드 반환 전달하는 경우
if [[ "$OS_NAME" == "mac_os" ]]; then 
     make all; 
     run_test1; 
     run_test2; 
     make install; 
    else 
     docker exec -i my_docker_image bash -c "make all"; 
     docker exec -i my_docker_image bash -c "run_test1"; 
     docker exec -i my_docker_image bash -c "run_test2"; 
     docker exec -i my_docker_image bash -c "make install"; 
    fi 

들이 오류 코드 1을 반환 0

전체 스크립트는 그래서 0이 아닌 종료 코드를 볼 때마다 중지하고 set -e으로 실행 전체 빌드를 실패합니다.

현재 run_test1run_test2이 조건절 안에있는 경우 문제가 발생합니다. 오류 코드 1이 실패하고 오류 코드 1을 반환하면 조건절이 중단되지 않고 테스트가 통과하지 못하고 빌드가 성공합니다. 명령 중 하나가 0이 아닌 에러 코드를 반환하는 경우

  • 방법 조건절을 깰 :

    그래서 나는이 개 질문이?

  • 전체 절이 오류 코드를 반환하는 방식으로 조건부 절을 끊는 방법 (전체 빌드가 실패합니다)?

    #!/usr/bin/env bash 
    
    set -e 
    
    var="test" 
    if [[ $var = test ]]; then 
        echo "Hello" 
        cat non_existing_file &> /dev/null 
        echo "World" 
    else 
        echo "Else hello" 
        cat non_existing file &> /dev/null 
    fi 
    
    echo I am done 
    

    이 출력됩니다 전용 "안녕하세요"를, 예상대로 예상대로

+1

귀하의 분석이 정확하지 않습니다. 'set -e'가 유효하고'run_test1'이 실패하면 스크립트는 여기서 멈 춥니 다. 뭔가 다른 일이 일어나면 코드의 일부가 표시되지 않았기 때문입니다. [문제를 증명하는 실제 코드] (https://stackoverflow.com/help/mcve)를 게시하십시오. 사용자가 makefile 및 도커 이미지를 사용하지 않고도 쉽게 실행할 수 있도록 단순화하는 것이 좋습니다. – Gilles

+1

http://mywiki.wooledge.org/BashFAQ/105 – pynexj

답변

1

코드는의이을 보여하자, 작동합니다. 다르게 작동하면 코드를 충분히 제공하지 못했음을 의미합니다.

Bash Reference manual을 인용 : 그냥 귀하의 경우와 같이, 위의 코드를 변경하고 set -e이 무시 될 때 몇 가지 예를 보여 해보자 화합물 명령 또는 쉘 함수는 컨텍스트에서 실행

경우 경우 -e 이 무시되는 경우 명령 또는 함수 본문 내에서 실행 된 명령은 -e가 설정되고 명령이 실패 상태를 반환하는 경우에도 -e 설정의 영향을받지 않습니다.

쉘 종료되지 않습니다 실패 명령이 즉시 동안 다음 명령 목록의 일부인 경우 또는 : 이제

의이 같은 매뉴얼을 인용하고 -e는 무시됩니다 일부의 경우를 보자 키워드가 될 때까지 부분의 테스트, 어떤 명령의 일부가 & & 또는 ||에서 실행됩니다. 최종 & & 다음의 명령 또는 ||, 모든 명령 , 파이프 라인의 마지막 명령, 또는 명령의 반환 상태가 인 경우!

#!/usr/bin/env bash 

set -e 

f() { 
    var="test" 
    if [[ $var = test ]]; then 
     echo "Hello" 
     cat non_existing_file &> /dev/null 
     echo "World" 
    else 
     echo "Else hello" 
     cat non_existing file &> /dev/null 
    fi 
} 

if f; then echo "Function OK!"; fi 

echo I am done 

기능 f가 실행됩니다 : 당신이 함수에서 위의 코드를했고 if와 그 기능을 테스트하는 경우이에서

우리는 set -e가 무시 될 것이다, 예를 들어, 그것을 볼 수 있습니다 여기서 set -e은 무시됩니다 (if 문). 즉, set -e은이 함수 내에서 실행 된 명령에 영향을 미치지 않습니다. 이 코드 출력 :

안녕하세요

기능 OK 세계

!

나는

당신이 & & 또는에서 함수를 실행할 때 동일한 규칙이 적용을 완료하고 || 명부. if f; then echo "Function OK!"; fi 행을 f && echo "Function OK"으로 변경하면 동일한 결과가 나옵니다. 후자가 귀하의 경우라고 생각합니다.

는 그럼에도 불구하고, 당신의 두 번째 질문|| exit을 추가하여 쉽게 해결할 수 있습니다 당신은 예를 들어, 함수 내부에있는 경우

run_test1 || exit 1; 
run_test2 || exit 1; 

귀하의 첫 번째 질문는 간단하다. 그런 다음 간단히 return 수 있습니다. 또는 루프 내부에서 break을 사용할 수 있습니다. 그렇지 않은 경우 조건부 조항을 벗어나는 것이 쉽지 않습니다. 이 answer을 살펴보십시오.

set -e은 많은 경우 무시되는 놀라운 일이 될 수 있습니다. 조심스럽게 사용하고 이러한 경우를 알고 있어야합니다.

관련 문제