Linux에서 Bash 스크립트의 오류를 트래핑하는 방법

게시 됨: 2022-08-27
bash 프롬프트를 표시하는 Linux 노트북
Fatmawati achmad zaenuri/Shutterstock.com

기본적으로 Linux의 Bash 스크립트는 오류를 보고하지만 계속 실행됩니다. 다음에 발생해야 할 일을 결정할 수 있도록 오류를 직접 처리하는 방법을 보여줍니다.

스크립트의 오류 처리

오류 처리는 프로그래밍의 일부입니다. 완벽한 코드를 작성하더라도 여전히 오류 조건이 발생할 수 있습니다. 컴퓨터의 환경은 소프트웨어를 설치 및 제거하고, 디렉터리를 만들고, 업그레이드 및 업데이트를 수행함에 따라 시간이 지남에 따라 변경됩니다.

PowerShell에서 매개변수 유효성 검사 오류 사용자 지정
관련 PowerShell의 매개변수 유효성 검사 오류 사용자 지정

예를 들어 문제 없이 실행되던 스크립트가 디렉토리 경로가 변경되거나 파일에 대한 권한이 변경되면 문제가 발생할 수 있습니다. Bash 셸의 기본 동작은 오류 메시지를 출력하고 스크립트를 계속 실행하는 것입니다. 이것은 위험한 기본값입니다.

실패한 작업이 스크립트에서 나중에 발생하는 다른 처리 또는 작업에 중요한 경우 해당 중요한 작업은 성공하지 못합니다. 그것이 얼마나 비참한지는 당신의 스크립트가 무엇을 하려고 하는지에 달려 있습니다.

보다 강력한 체계는 오류를 감지하고 스크립트를 종료해야 하거나 오류 상태를 수정해야 하는 경우 스크립트가 작동하도록 합니다. 예를 들어, 디렉토리나 파일이 누락된 경우 스크립트에서 이를 다시 생성하는 것으로 만족할 수 있습니다.

스크립트에 복구할 수 없는 문제가 발생한 경우 스크립트가 종료될 수 있습니다. 스크립트를 종료해야 하는 경우 임시 파일을 제거하거나 오류 조건 및 종료 이유를 로그 파일에 기록하는 등 필요한 모든 정리를 수행할 수 있습니다.

종료 상태 감지

명령과 프로그램은 종료될 때 운영 체제로 전송되는 값을 생성합니다. 이를 종료 상태라고 합니다. 오류가 없으면 값이 0이고 오류가 발생하면 0이 아닌 값이 있습니다.

우리는 스크립트가 사용하는 명령의 종료 상태(반환 코드라고도 함)를 확인하고 명령이 성공했는지 여부를 결정할 수 있습니다.

Bash에서 0은 true와 같습니다. 명령의 응답이 true가 아닌 경우 문제가 발생했음을 알고 적절한 조치를 취할 수 있습니다.

이 스크립트를 편집기에 복사하고 "bad_command.sh"라는 파일에 저장합니다.

 #!/bin/bash

if ( ! bad_command ); 그 다음에
  echo "bad_command가 오류를 표시했습니다."
  1번 출구
파이

chmod 명령을 사용하여 스크립트를 실행 가능하게 만들어야 합니다. 이것은 스크립트를 실행 가능하게 만드는 데 필요한 단계이므로 자신의 컴퓨터에서 스크립트를 시험해 보려면 각 스크립트에 대해 이 작업을 수행하는 것을 기억하십시오. 각 경우에 적절한 스크립트의 이름을 대체하십시오.

 chmod +x bad_command.sh 

chmod를 사용하여 스크립트를 실행 가능하게 만들기

스크립트를 실행하면 예상한 오류 메시지가 표시됩니다.

 ./bad_command.sh 

오류가 있는지 여부를 확인하기 위해 명령의 종료 상태 확인

"bad_command"와 같은 명령은 없으며 스크립트 내의 함수 이름도 아닙니다. 실행할 수 없으므로 응답이 0이 아닙니다 . 응답이 0이 아니면(여기서 느낌표가 논리 NOT 연산자로 사용됨) if 문의 본문이 실행됩니다.

실제 스크립트에서 이것은 우리의 예와 같이 스크립트를 종료하거나 오류 조건을 수정하려고 시도할 수 있습니다.

exit 1 라인이 중복된 것처럼 보일 수 있습니다. 결국 스크립트에는 다른 것이 없으며 어쨌든 종료됩니다. 그러나 exit 명령을 사용하면 종료 상태를 쉘로 다시 전달할 수 있습니다. 스크립트가 두 번째 스크립트 내에서 호출된 경우 해당 두 번째 스크립트는 이 스크립트에 오류가 발생했음을 알 수 있습니다.

명령의 종료 상태와 함께 논리 OR 연산자를 사용하고 첫 번째 명령에서 0이 아닌 응답이 있는 경우 스크립트에서 다른 명령이나 함수를 호출할 수 있습니다.

 명령_1 || 명령_2

이것은 첫 번째 명령이 실행 OR 두 번째 명령이 실행되기 때문에 작동합니다. 맨 왼쪽 명령이 먼저 실행됩니다. 성공하면 두 번째 명령이 실행되지 않습니다. 그러나 첫 번째 명령이 실패하면 두 번째 명령이 실행됩니다. 따라서 우리는 이와 같은 코드를 구성할 수 있습니다. 이것은 "logical-or./sh"입니다.

 #!/bin/bash

error_handler()
{
  echo "오류: ($?) $1"
  1번 출구
}

나쁜 명령 || error_handler "bad_command 실패, 행: ${LINENO}"

error_handler 라는 함수를 정의했습니다. 이것은 $? 변수에 보관된 실패한 명령의 종료 상태를 출력합니다. 함수가 호출될 때 전달되는 텍스트 줄입니다. 이것은 변수 $1 에 보관됩니다. 이 함수는 종료 상태가 1인 스크립트를 종료합니다.

스크립트는 분명히 실패하는 bad_command 를 실행하려고 시도하므로 논리적 OR 연산자의 오른쪽에 있는 명령 || , 실행됩니다. 이것은 error_handler 함수를 호출하고 실패한 명령의 이름을 지정하고 실패한 명령의 행 번호를 포함하는 문자열을 전달합니다.

스크립트를 실행하여 오류 처리기 메시지를 확인한 다음 echo를 사용하여 스크립트의 종료 상태를 확인합니다.

 ./논리적 또는.sh
 에코 $? 

논리적 OR 연산자를 사용하여 스크립트에서 오류 처리기 호출

우리의 작은 error_handler 함수는 bad_command 실행 시도의 종료 상태, 명령 이름 및 줄 번호를 제공합니다. 이것은 스크립트를 디버깅할 때 유용한 정보입니다.

스크립트의 종료 상태는 1입니다. error_handler 가 보고한 127 종료 상태는 "명령을 찾을 수 없음"을 의미합니다. 원하는 경우 exit 명령에 전달하여 스크립트의 종료 상태로 사용할 수 있습니다.

또 다른 접근 방식은 error_handler 를 확장하여 종료 상태의 다른 가능한 값을 확인하고 이에 따라 다음 유형의 구성을 사용하여 다른 작업을 수행하는 것입니다.

 exit_code=$?

if [ $exit_code -eq 1 ]; 그 다음에
  echo "허용되지 않는 작업"

elif [ $exit_code -eq 2 ]; 그 다음에
  echo "셸 빌트인의 오용"
.
.
.
elif [ $ 상태 -eq 128 ]; 그 다음에
  echo "잘못된 인수"
파이

강제 종료 설정 사용

오류가 있을 때마다 스크립트가 종료되기를 원한다면 강제로 종료할 수 있습니다. 이는 스크립트가 오류를 감지하는 즉시 종료되기 때문에 정리 또는 추가 손상 가능성을 포기한다는 의미입니다.

이렇게 하려면 -e (오류) 옵션과 함께 set 명령을 사용합니다. 이것은 명령이 실패하거나 0보다 큰 종료 코드를 반환할 때마다 스크립트를 종료하도록 지시합니다. 또한 -E 옵션을 사용하면 쉘 기능에서 오류 감지 및 트래핑이 작동합니다.

Linux의 Bash 스크립트에서 set 및 pipefail을 사용하는 방법
관련 Linux의 Bash 스크립트에서 set 및 pipefail을 사용하는 방법

초기화되지 않은 변수도 catch하려면 -u (설정되지 않음) 옵션을 추가합니다. 파이프 시퀀스에서 오류가 감지되었는지 확인하려면 -o pipefail 옵션을 추가하십시오. 이것이 없으면 파이프된 명령 시퀀스의 종료 상태는 시퀀스의 마지막 명령의 종료 상태입니다. 파이프된 시퀀스 중간에 실패한 명령은 감지되지 않습니다. -o pipefail 옵션은 옵션 목록에 있어야 합니다.

스크립트 상단에 추가할 순서는 다음과 같습니다.

 set -Eeuo pipefail

다음은 설정되지 않은 변수가 포함된 "unset-var.sh"라는 짧은 스크립트입니다.

 #!/bin/bash

set -어우 pipefail

echo "$unset_variable"

echo "이 줄이 보이나요?"

스크립트를 실행하면 unset_variable이 초기화되지 않은 변수로 인식되고 스크립트가 종료됩니다.

 ./unset-var.sh 

스크립트에서 set 명령을 사용하여 오류 발생 시 스크립트 종료

두 번째 echo 명령은 실행되지 않습니다.

오류가 있는 트랩 사용

Bash 트랩 명령을 사용하면 특정 신호가 발생할 때 호출되어야 하는 명령이나 함수를 지정할 수 있습니다. 일반적으로 이것은 Ctrl+C 키 조합을 누를 때 발생하는 SIGINT 와 같은 신호를 잡는 데 사용됩니다. 이 스크립트는 "signint.sh"입니다.

 #!/bin/bash

트랩 "echo -e '\nCtrl+c'로 종료됨, 종료" SIGINT

카운터=0

사실 동안
하다 
  echo "루프 번호:" $((++counter))
  수면 1
완료

trap 명령에는 echo 명령과 exit 명령이 포함됩니다. SIGINT 가 발생하면 트리거됩니다. 나머지 스크립트는 간단한 루프입니다. 스크립트를 실행하고 Ctrl+C를 누르면 trap 정의의 메시지가 표시되고 스크립트가 종료됩니다.

 ./signint.sh 

스크립트에서 트랩을 사용하여 Ctrl+c 잡기

오류가 발생할 때 오류를 포착하기 위해 ERR 신호와 함께 trap 을 사용할 수 있습니다. 그런 다음 명령이나 기능에 공급할 수 있습니다. "trap.sh"입니다. error_handler 라는 함수에 오류 알림을 보내고 있습니다.

 #!/bin/bash

트랩 'error_handler $? $LINENO' 오류

error_handler() {
  echo "오류: ($1)이 $2에서 발생했습니다"
}

기본() {
  echo "main() 함수 내부"
  나쁜 명령
  초
  제삼
  종료 $?
}

초() {
  echo "main() 호출 후"
  echo "second() 함수 내부"
}

세 번째() {
  echo "third() 함수 내부"
}

기본

스크립트의 대부분은 secondthird 함수를 호출하는 main 함수 내부에 있습니다. 오류가 발생하면(이 경우 bad_command 가 존재하지 않기 때문에) trap 문은 오류를 error_handler 함수로 보냅니다. 실패한 명령의 종료 상태와 줄 번호를 error_handler 함수에 전달합니다.

 ./트랩.sh 

ERR과 함께 트랩을 사용하여 스크립트에서 오류 포착

error_handler 함수는 단순히 오류의 세부 정보를 터미널 창에 나열합니다. 원하는 경우 함수에 exit 명령을 추가하여 스크립트를 종료할 수 있습니다. 또는 일련의 if/elif/fi 문을 사용하여 다른 오류에 대해 다른 작업을 수행할 수 있습니다.

일부 오류를 수정하는 것이 가능할 수도 있고 다른 오류는 스크립트를 중지해야 할 수도 있습니다.

마지막 팁

오류를 포착한다는 것은 종종 잘못될 수 있는 일을 선점하고 이러한 결과가 발생할 경우 처리할 코드를 넣는 것을 의미합니다. 이는 스크립트의 실행 흐름과 내부 논리가 올바른지 확인하는 것 외에도 있습니다.

이 명령을 사용하여 스크립트를 실행하면 Bash는 스크립트가 실행될 때 추적 출력을 표시합니다.

 bash -x your-script.sh

Bash는 터미널 창에 추적 출력을 씁니다. 인수가 있는 경우 각 명령을 해당 인수와 함께 표시합니다. 이것은 명령이 확장된 후 실행되기 전에 발생합니다.

찾기 힘든 버그를 추적하는 데 큰 도움이 될 수 있습니다.

관련: Linux Bash 스크립트를 실행하기 전에 구문을 확인하는 방법