모든 명령은 종료 상태를 남겨
Unix 프로세스는 끝날 때 정수 상태를 부모 프로세스에 돌려줘. 셸은 가장 최근 전경 명령의 상태를 $?에 저장하고, 관례상 0은 성공, 0이 아닌 값은 성공하지 못했음을 뜻해. 숫자의 자세한 의미는 명령마다 다를 수 있으므로 메시지와 문서를 함께 봐야 해. $?는 다음 명령을 실행하면 즉시 바뀌므로 필요하다면 바로 변수에 저장해.
자주 만나는 상태 값
- 0: 요청한 작업을 성공적으로 마쳤어.
- 1: 일반 실패이거나,
grep처럼 “일치 항목 없음”을 뜻할 수 있어. - 2: 잘못된 사용법이나 입력 오류로 쓰이는 경우가 많아.
- 126: 명령은 찾았지만 실행할 수 없어.
- 127: 명령을 찾지 못했어.
- 128+N: 신호 N 때문에 끝난 관례적 표현이야. 예를 들어 SIGINT는 흔히 130으로 보여.
이 목록은 셸 관례이지 모든 프로그램의 완전한 명세가 아니야. 자동화에서는 사용하는 명령의 문서를 확인해.
성공과 실패에 따라 다음 명령을 골라
cmd1 && cmd2는 첫 명령이 성공했을 때만 두 번째를 실행하고, cmd1 || cmd2는 첫 명령이 성공하지 못했을 때 두 번째를 실행해. 세미콜론은 앞 결과와 상관없이 다음 명령을 실행해. 짧은 검사에는 유용하지만 여러 실패 종류를 모두 같은 분기로 뭉개면 원인을 잃을 수 있어. “대상이 없음”과 “권한 때문에 읽지 못함”을 구분해야 하는 작업이라면 명시적인 if와 상태 검사로 적어.
스크립트와 함수도 결과를 선언해
스크립트의 exit N은 프로세스 종료 상태를 정하고, 함수의 return N은 호출한 셸 코드에 상태를 돌려줘. 오류를 복구했다면 무엇을 복구했는지 기록하고, 결과가 유효하지 않다면 0이 아닌 상태를 반환해야 해. 실패하면서 0을 반환하면 CI, 모니터와 상위 스크립트가 거짓 성공을 믿게 돼.
파이프라인에서는 어느 단계의 상태인지 확인해
기본적으로 파이프라인의 상태는 마지막 명령의 상태야. producer | consumer에서 producer가 실패해도 consumer가 정상 종료하면 전체가 성공처럼 보일 수 있어. bash와 zsh에서 set -o pipefail로 켜는 pipefail 옵션은 앞 단계의 실패를 드러내는 데 도움을 주지만, 각 셸에서의 동작과 실행 환경을 확인해야 해. 중요한 파이프라인은 결과 데이터뿐 아니라 중간 단계의 오류도 관찰할 수 있게 만들어.