문제

여러 명령을 실행하는 쉘 스크립트가 있습니다.명령이 0이 아닌 종료 코드로 종료되는 경우 쉘 스크립트를 어떻게 종료합니까?

도움이 되었습니까?

해결책

각 명령 다음에 종료 코드는 다음에서 찾을 수 있습니다. $? 변수를 사용하면 다음과 같은 결과를 얻을 수 있습니다.

ls -al file.ext
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

파이프된 명령에 주의해야 합니다. $? 파이프의 마지막 요소에 대한 반환 코드만 제공하므로 코드에서는 다음과 같습니다.

ls -al file.ext | sed 's/^/xx: /"

파일이 존재하지 않으면 오류 코드를 반환하지 않습니다. sed 파이프라인의 일부가 실제로 작동하여 0을 반환합니다.

그만큼 bash 쉘은 실제로 그러한 경우에 도움이 될 수 있는 배열을 제공합니다. PIPESTATUS.이 배열에는 다음과 같이 개별적으로 액세스할 수 있는 각 파이프라인 구성요소에 대해 하나의 요소가 있습니다. ${PIPESTATUS[0]}:

pax> false | true ; echo ${PIPESTATUS[0]}
1

이는 다음의 결과를 얻는다는 점에 유의하세요. false 전체 파이프라인이 아닌 명령입니다.또한 적합하다고 판단되는 대로 전체 목록을 처리할 수도 있습니다.

pax> false | true | false; echo ${PIPESTATUS[*]}
1 0 1

파이프라인에서 가장 큰 오류 코드를 얻으려면 다음과 같이 사용할 수 있습니다.

true | true | false | true | false
rcs=${PIPESTATUS[*]}; rc=0; for i in ${rcs}; do rc=$(($i > $rc ? $i : $rc)); done
echo $rc

이는 각 과정을 거쳐 PIPESTATUS 요소를 차례로 저장합니다. rc 이전보다 더 컸다면 rc 값.

다른 팁

$?로 작업하려면 $? 이후 각 명령 후에 이를 확인해야 합니다.각 명령이 종료된 후에 업데이트됩니다.즉, 파이프라인을 실행하면 파이프라인의 마지막 프로세스의 종료 코드만 얻게 됩니다.

또 다른 접근 방식은 다음과 같습니다.

set -e
set -o pipefail

이것을 쉘 스크립트의 맨 위에 놓으면 bash가 이를 처리해 줄 것 같습니다.이전 포스터에서 언급했듯이 "set -e"를 사용하면 간단한 명령에서 오류와 함께 bash가 종료됩니다."set -o Pipefail"을 사용하면 파이프라인의 모든 명령에서도 오류가 발생하면서 bash가 종료됩니다.

보다 여기 또는 여기 이 문제에 대해 좀 더 논의해 보겠습니다. 여기 세트 내장의 bash 매뉴얼 섹션입니다.

"set -e" 아마도 이 작업을 수행하는 가장 쉬운 방법일 것입니다.프로그램의 모든 명령 앞에 이를 입력하면 됩니다.

매개 변수 없이 bash에서 그냥 종료를 호출하면 마지막 명령의 종료 코드가 반환됩니다.OR와 결합하면 bash는 이전 명령이 실패한 경우에만 종료를 호출해야 합니다.그러나 나는 이것을 테스트하지 않았습니다.

command1 || exit;
command2 || exit;

Bash는 마지막 명령의 종료 코드도 변수 $?에 저장합니다.

[ $? -eq 0 ] || exit $?; # exit for none-zero return code

http://cfaj.freeshell.org/shell/cus-faq-2.html#11

  1. 종료 코드를 어떻게 얻나요? cmd1 ~에 cmd1|cmd2

    먼저, cmd1 출구 코드는 0이 아니지만 여전히 오류를 의미하지는 않습니다.예를 들어 이런 일이 발생합니다.

    cmd | head -1
    

    141(또는 ksh93의 경우 269) 종료 상태를 볼 수 있습니다. cmd1,하지만 그 때문입니다 cmd SIGPIPE 신호에 의해 중단되었습니다.head -1 한 줄을 읽은 후 종료됩니다.

    파이프라인 요소의 종료 상태를 확인하려면cmd1 | cmd2 | cmd3

    ㅏ.zsh를 사용하면:

    종료 코드는 Pipestatus 특수 배열에 제공됩니다. cmd1 종료 코드가 있습니다 $pipestatus[1], cmd3 종료 코드 $pipestatus[3], 하도록 하다 $? 항상 같다 $pipestatus[-1].

    비.배쉬와 함께:

    종료 코드는 PIPESTATUS 특별한 배열. cmd1 종료 코드가 있습니다 ${PIPESTATUS[0]}, cmd3 종료 코드 ${PIPESTATUS[2]}, 하도록 하다 $? 항상 같다 ${PIPESTATUS: -1}.

    ...

    자세한 내용은 다음을 참조하세요 링크.

배쉬의 경우:

# this will trap any errors or commands with non-zero exit status
# by calling function catch_errors()
trap catch_errors ERR;

#
# ... the rest of the script goes here
#  

function catch_errors() {
   # do whatever on errors
   # 
   #
   echo "script aborted, because of errors";
   exit 0;
}

Bash에서는 쉽습니다. &&로 묶으면 됩니다.

command1 && command2 && command3

중첩된 if 구문을 사용할 수도 있습니다.

if command1
   then
       if command2
           then
               do_something
           else
               exit
       fi
   else
       exit
fi
#
#------------------------------------------------------------------------------
# run a command on failure exit with message
# doPrintHelp: doRunCmdOrExit "$cmd"
# call by:
# set -e ; doRunCmdOrExit "$cmd" ; set +e
#------------------------------------------------------------------------------
doRunCmdOrExit(){
    cmd="$@" ;

    doLog "DEBUG running cmd or exit: \"$cmd\""
    msg=$($cmd 2>&1)
    export exit_code=$?

    # if occured during the execution exit with error
    error_msg="Failed to run the command:
        \"$cmd\" with the output:
        \"$msg\" !!!"

    if [ $exit_code -ne 0 ] ; then
        doLog "ERROR $msg"
        doLog "FATAL $msg"
        doExit "$exit_code" "$error_msg"
    else
        #if no errors occured just log the message
        doLog "DEBUG : cmdoutput : \"$msg\""
        doLog "INFO  $msg"
    fi

}
#eof func doRunCmdOrExit
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top