명령 오류가 발생하면 bash 스크립트의 함수를 자동으로 실행하는 방법이 있습니까?

명령 오류가 발생하면 bash 스크립트의 함수를 자동으로 실행하는 방법이 있습니까?

저는 여러 명령을 실행해야 하는 쉘 스크립트를 작성하고 있는데, 각 명령은 이전의 모든 명령에 따라 달라집니다. 명령이 실패하면 전체 스크립트가 실패하고 종료 함수를 호출합니다. 각 명령의 종료 코드를 확인할 수 있지만 활성화할 수 있는 모드가 있는지 또는 bash에서 이 작업을 자동으로 수행하도록 하는 방법이 있는지 알고 싶습니다.

예를 들어, 다음 명령을 사용하십시오.

cd foo || myfunc
rm a || myfunc
cd bar || myfunc
rm b || myfunc


이 명령을 실행하기 전에 명령 중 하나라도 실패하면 myfunc를 호출하여 다음과 같이 더 깔끔하게 작성할 수 있도록 쉘에 신호를 보낼 수 있는 방법이 있습니까?

cd foo
rm a
cd bar
rm b

답변1

배쉬를 사용할 수 있습니다트랩 오류명령이 0보다 큰 상태를 반환하는 경우 스크립트를 종료하고 종료 시 함수를 실행합니다.

그것은 다음과 같습니다:

myfunc() {
  echo 'Error raised. Exiting!'
}

trap 'myfunc' ERR

# file does not exist, causing error
ls asd
echo 123

알아채다슬램 트랩 ERR암시적 set -o errexitor set -e및 는 POSIX가 아닙니다.

실패한 명령이 또는 키워드 바로 다음 명령 목록의 일부이거나, 또는 예약어 뒤의 테스트의 일부이거나, 또는 목록에서 실행된 명령의 일부이거나, 명령의 반환 상태가 반전을 사용하는 경우 ERR, 트랩이 실행되지 않습니다.untilwhileifelif&&||!

답변2

허용되는 답변의 (아마도) 더 간단한 변형입니다.

  1. set -e 명령이 실패하고 목록 실행이 중단되도록 하는 데 사용됩니다 .
  2. 명령을 나열하면 됩니다.
  3. if- then- 문을 사용하여 else오류 처리 명령을 실행합니다. 마지막 부분이 좀 까다롭네요. 보다:
세트이
만약에
    명령 1                        # 예를 들어, cd foo
    명령 2                        # 예를 들어, rm a
    명령 3                        # 예를 들어 CD바
    명령 4                        # 예를 들어, rm b
그 다음에
    세트+e
    성공 시 실행할 명령(있는 경우)
기타
    세트+e
    내 기능
    실패 시 실행할 추가 명령(있는 경우)
필리핀 제도

까다로운 부분은 명령을 입력한다는 것입니다. 입력하다if부분부분이나 부분 대신 - if- then를 사용하세요 . 그것을 기억해elsethenelseif문의 구문

만약에 목록;그 다음에 목록;[ 일라이프 목록;그 다음에 목록;] ... [ 기타 목록;] 페이
   ↑↑↑↑
set -e( )가 실패하면 ( ) 실행을 계속해서는 안 된다는 점을 쉘에 알려줍니다 . 쉘 스크립트의 가장 바깥쪽 명령에 이런 일이 발생하면 쉘이 종료됩니다. 그러나... 이후는 (복합) 목록이고 그 뒤에는cmd1cd foocmd2rm acmd1cmd2cmd3cmd4if, 이 네 가지 명령 중 하나라도 실패하면 전체 목록이 실패하게 되어 해당 절이 else실행됩니다. 네 가지 명령이 모두 성공하면 then이 절이 실행됩니다.

e두 경우 모두 가장 먼저 해야 할 일은 다음을 수행하여 옵션을 비활성화(끄기)하는 것입니다 set +e. 그렇지 않으면 명령이 실패하면 myfunc스크립트가 물 밖으로 날아갈 수 있습니다 .

set -ePOSIX 사양에 지정 및 설명됨.

답변3

약속을 지키세요”각 명령은 모든 이전 명령에 따라 달라집니다. 명령이 실패하면 전체 스크립트가 실패합니다."말 그대로 오류를 처리하기 위해 특별한 기능이 필요하다고 생각하지 않습니다.

당신이 해야 할 일은 &&연산자와 ||연산자를 사용하여 명령을 연결하는 것 뿐이며, 그것이 바로 당신이 작성하는 것입니다.

예를 들어, 다음과 같은 경우 체인이 끊어지고 "뭔가 잘못되었습니다"라고 인쇄됩니다.어느이전 명령이 손상되었습니다(Bash는 왼쪽에서 오른쪽으로 읽습니다).

cd foo && rm a && cd bar && rm b || echo "something went wrong"

실제 예(실제 데모를 위해 dir foo, file a, dir bar 및 file b를 만들었습니다):

gv@debian:/home/gv/Desktop/PythonTests$ cd foo && rm a && cd bar && rm bb || echo "something is wrong"
rm: cannot remove 'bb': No such file or directory
something is wrong #mind the error in the last command

gv@debian:/home/gv/Desktop/PythonTests$ cd foo && rm aa && cd bar && rm b || echo "something is wrong"
rm: cannot remove 'aa': No such file or directory
something is wrong #mind the error in second command in the row

마지막으로 모든 명령이 성공적으로 실행되면(종료 코드 0) 스크립트가 계속 실행됩니다.

gv@debian:/home/gv/Desktop/PythonTests$ cd foo && rm a && cd bar && rm b || echo "something is wrong"
gv@debian:/home/gv/Desktop/PythonTests/foo/bar$ 
# mind that the error message is not printed since all commands were successful.

&&를 사용할 때 이전 명령이 코드 0으로 종료되면 다음 명령이 실행되며 이는 bash의 성공을 의미한다는 점을 기억하는 것이 중요합니다.

체인의 명령 중 하나라도 잘못되면 command/script/|| 다음의 모든 명령이 실행됩니다.

기록을 위해 중단된 명령에 따라 다른 작업을 수행해야 하는 경우 $?이전 명령의 종료 코드를 보고하는 값을 모니터링하여 기존 스크립트를 사용하여 이 작업을 수행할 수도 있습니다(명령이 성공적으로 실행되었거나 0을 반환하는 경우). 명령이 그렇지 않으면 양수입니다)

예:

for comm in {"cd foo","rm a","cd bbar","rm b"};do  #mind the error in third command
eval $comm
    if [[ $? -ne 0 ]];then 
        echo "something is wrong in command $comm"
        break
    else 
    echo "command $comm executed succesful"
    fi
done

산출:

command cd foo executed succesfull
command rm a executed succesfull
bash: cd: bbar: No such file or directory
something is wrong in command cd bbar

팁: 앱을 통해 "bash: cd: bbar: No such file..." 메시지를 표시하지 않을 수 있습니다.eval $comm 2>/dev/null

관련 정보