소개
누군가에게 일을 부탁할 때마다 그 사람이 작업을 마친 뒤 작은 카드를 건넨다고 상상해 보세요.
- **초록색 카드 (0)**는 "완벽하게 처리했습니다"를 의미합니다.
- **빨간색 카드 (1-255)**는 "문제가 발생했습니다"를 의미합니다.
Linux 에서는 모든 명령이 정확히 이런 방식으로 동작합니다. 이를 종료 코드 (exit code) 또는 **종료 상태 (exit status)**라고 합니다.
0: 성공0이 아님: 실패
대부분의 초보자는 이 코드를 확인하지 않으면 보이지 않기 때문에 무시합니다. 하지만 전문 스크립트 작성자는 종료 상태를 주의 깊게 확인합니다. 종료 상태는 명령과 스크립트 사이에서 성공 또는 실패를 알리는 셸의 주요 수단 중 하나이기 때문입니다.
이는 Unix 의 핵심 설계 방식입니다. 작은 프로그램들은 단순한 규칙을 사용해 서로 통신합니다. 텍스트는 표준 출력으로 전달되고, 성공 또는 실패는 종료 상태로 전달됩니다. 자동화에서 종료 코드가 중요한 이유가 바로 여기에 있습니다.
이 실습에서는 변수 $?를 사용해 이 비밀 카드를 읽고, 스크립트가 문제를 일으키기 전에 중지하는 방법을 배웁니다.
$?로 명령 상태 확인
보이지 않는 "성적표"를 어떻게 확인할까요? 명령을 실행한 직후 특수 변수 $?를 확인하면 됩니다.
먼저 성공하는 경우를 살펴보겠습니다.
터미널을 열고 파일을 목록으로 표시합니다.
ls -l
정상적으로 실행되었지요? 이제 "점수가 몇 점이었을까?"라고 물어보겠습니다.
echo $?
0이 표시됩니다. Linux 에서는 0 을 오류의 개수로 생각할 수 있습니다. 오류가 0 개라는 것은 완벽하게 성공했다는 뜻입니다.
이번에는 일부러 실패를 발생시켜 보겠습니다. 존재하지 않는 파일을 목록으로 표시합니다.
ls ghosts.txt
Linux 에서 파일을 찾을 수 없다는 오류 메시지가 표시됩니다. 이제 점수를 다시 확인합니다.
echo $?
2가 표시됩니다. 0 이 아니므로 실패입니다.
정확한 0 이 아닌 숫자는 명령과 상황에 따라 달라질 수 있습니다. 하지만 지금 기억해야 할 핵심 규칙은 간단합니다. 0은 성공이고, 그 외의 값은 실패입니다. 나중에 스크립트와 도구를 사용하다 보면 일부 프로그램이 서로 다른 종류의 문제를 나타내기 위해 여러 0 이 아닌 종료 코드를 사용하는 것을 확인하게 됩니다.
중요한 규칙: $?는 단기 기억만 저장합니다. $?는 바로 직전에 실행한 작업만 기억합니다. ls를 실행해 실패한 다음 echo "hello"를 실행하고 $?를 확인하면, echo가 성공했기 때문에 0이 표시됩니다. 반드시 명령을 실행한 직후 확인해야 합니다.
실패하는 스크립트 만들기
여기에는 위험 요소가 있습니다. 기본적으로 스크립트는 빨간색 카드를 무시하고 계속 실행합니다.
다음과 같은 스크립트를 생각해 보세요.
- 백업을 만듭니다.
- 원본 파일을 삭제합니다.
1 단계가 실패하면 (백업 공간이 가득 찬 경우) 2 단계가 계속 실행되어 모든 파일을 잃게 됩니다.
이 "눈먼 스크립트"를 직접 시뮬레이션해 보겠습니다.
copy_script.sh를 만듭니다.
nano copy_script.sh
다음 코드를 입력합니다. 이 코드는 존재하지 않는 파일을 복사한 뒤 성공했다고 알립니다.
#!/bin/bash
## Attempt to copy a ghost
cp ghost_file.txt destination.txt
## Print a happy message
echo "Script finished execution"
파일을 저장하고 종료합니다. 실행 권한을 부여합니다.
chmod +x copy_script.sh
실행합니다.
./copy_script.sh
cp의 오류 메시지가 표시된 다음 "Script finished execution"도 표시됩니다. 스크립트는 실패했지만 계속 실행된 것입니다!
스크립트 자체의 점수를 확인합니다.
echo $?
0이 반환됩니다. 왜 그럴까요? 마지막 명령 (echo) 이 성공했기 때문입니다. 이 스크립트는 거짓말을 하고 있습니다. 주요 작업에는 실패했지만 시스템에는 성공했다고 보고합니다.
여기서 중요한 점을 배울 수 있습니다. 셸 스크립트에도 종료 상태가 있으며, 특별히 처리하지 않으면 종료 상태는 실행된 마지막 명령의 종료 상태가 되는 경우가 많습니다. 따라서 스크립트 앞부분에서 발생한 실패가 실수로 숨겨질 수 있습니다.
오류 처리 구현
스크립트가 빨간불을 만나면 멈추도록 만들어야 합니다.
일반적으로 다음과 같은 구조를 사용합니다. "명령 X 를 실행합니다. 종료 코드가 0 이 아니면 즉시 중단합니다."
[ $? -ne 0 ] 구문은 여기에서 대괄호 형식으로 작성한 test 명령을 사용합니다. -ne는 숫자에서 "같지 않음"을 의미합니다. 따라서 셸은 "이전 명령의 종료 상태가 0 과 같지 않은가?"라고 확인합니다.
copy_script.sh를 편집합니다.
nano copy_script.sh
내용을 다음과 같이 변경합니다.
#!/bin/bash
cp ghost_file.txt destination.txt
## Check if the score is NOT equal (-ne) to 0
if [ $? -ne 0 ]; then
echo "Error: The copy operation failed!"
exit 1
fi
echo "Script finished execution"
코드 해석:
if [ $? -ne 0 ]: 검사 장치가 카드를 확인합니다.exit 1: 빨간색 버튼입니다. 스크립트를 즉시 종료하고 전역 점수를 1(오류) 로 설정합니다.
exit 명령은 현재 셸 스크립트를 종료하고, 해당 숫자를 스크립트를 실행한 대상에 반환합니다. 실행한 대상은 터미널, 다른 스크립트 또는 자동화 시스템일 수 있습니다. 즉, 로컬에서 실행만 중지하는 것이 아니라 외부 시스템에 상태도 보고하는 것입니다.
파일을 저장하고 종료합니다.
다시 실행합니다.
./copy_script.sh
스크립트는 오류를 출력하고 종료됩니다. "Script finished execution"은 출력하지 않습니다.
점수를 확인합니다.
echo $?
1이 표시됩니다. 이제 스크립트가 실패 사실을 정확하게 보고합니다.
요약
이제 명령의 비밀 언어를 읽는 방법을 배웠습니다.
이 실습에서는 다음 내용을 연습했습니다.
- 성적표 읽기:
$?를 사용해 명령이 성공했는지 (0), 실패했는지 (1-255) 확인합니다. - 거짓말하는 스크립트 드러내기: 주의하지 않으면 스크립트가 오류를 숨길 수 있다는 점을 확인합니다.
- 심판 역할 수행하기: 문제가 발생하면
exit 1을 사용해 실행을 중지합니다.
이 "확인 후 종료" 패턴이 허술한 스크립트와 전문적인 스크립트를 구분합니다.



