
저는 여러 명령을 실행해야 하는 쉘 스크립트를 작성하고 있는데, 각 명령은 이전의 모든 명령에 따라 달라집니다. 명령이 실패하면 전체 스크립트가 실패하고 종료 함수를 호출합니다. 각 명령의 종료 코드를 확인할 수 있지만 활성화할 수 있는 모드가 있는지 또는 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 errexit
or set -e
및 는 POSIX가 아닙니다.
실패한 명령이 또는 키워드 바로 다음 명령 목록의 일부이거나, 또는 예약어 뒤의 테스트의 일부이거나, 또는 목록에서 실행된 명령의 일부이거나, 명령의 반환 상태가 반전을 사용하는 경우 ERR
, 트랩이 실행되지 않습니다.until
while
if
elif
&&
||
!
답변2
허용되는 답변의 (아마도) 더 간단한 변형입니다.
set -e
명령이 실패하고 목록 실행이 중단되도록 하는 데 사용됩니다 .- 명령을 나열하면 됩니다.
if
-then
- 문을 사용하여else
오류 처리 명령을 실행합니다. 마지막 부분이 좀 까다롭네요. 보다:
세트이 만약에 명령 1 # 예를 들어, cd foo 명령 2 # 예를 들어, rm a 명령 3 # 예를 들어 CD바 명령 4 # 예를 들어, rm b 그 다음에 세트+e 성공 시 실행할 명령(있는 경우) 기타 세트+e 내 기능 실패 시 실행할 추가 명령(있는 경우) 필리핀 제도
까다로운 부분은 명령을 입력한다는 것입니다.
입력하다그 if
부분부분이나 부분 대신 - if
- then
를 사용하세요 . 그것을 기억해else
then
else
if
문의 구문예
만약에 목록;그 다음에 목록;[ 일라이프 목록;그 다음에 목록;] ... [ 기타 목록;] 페이 ↑↑↑↑
set -e
( )가 실패하면 ( ) 실행을 계속해서는 안 된다는 점을 쉘에 알려줍니다 . 쉘 스크립트의 가장 바깥쪽 명령에 이런 일이 발생하면 쉘이 종료됩니다. 그러나... 이후는 (복합) 목록이고 그 뒤에는cmd1
cd foo
cmd2
rm a
cmd1
cmd2
cmd3
cmd4
if
, 이 네 가지 명령 중 하나라도 실패하면 전체 목록이 실패하게 되어 해당 절이 else
실행됩니다. 네 가지 명령이 모두 성공하면 then
이 절이 실행됩니다.
e
두 경우 모두 가장 먼저 해야 할 일은 다음을 수행하여 옵션을 비활성화(끄기)하는 것입니다 set +e
. 그렇지 않으면 명령이 실패하면 myfunc
스크립트가 물 밖으로 날아갈 수 있습니다 .
set -e
예POSIX 사양에 지정 및 설명됨.
답변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