macOS 초보를 위한 터미널 사용 가이드 - Week 07
작성중인 문서
- 이전 문서: [[/mac/terminal-guide/06]]
$? 으로 종료상태값 확인하기
지난 주에 rm -f
를 설명할 때 $?
값을 출력해 보았습니다.
UNIX 시스템에서 모든 프로세스는 종료상태값을 갖습니다.
$?
는 직전에 실행된 망령의 종료상태값을 담고 있는 특수한 변수입니다.
값의 범위는 다양하지만 가장 중요한 값은 0
입니다.
이 글을 읽는 여러분은 초보자이니 대부분의 경우에는 0
만 알아도 한동안은 충분할 수 있습니다.
0
: 에러 없음. 정상 종료.1
~125
: UNIX 시스템 정의 에러 코드.126
: 실행 권한이 없음.127
: 명령을 찾을 수 없음.130
:control c
로 종료됨.
정상적으로 실행되어 에러 없이 종료되면 0
입니다.
저는 옛날에 이 값을 "에러 빵"으로 기억했습니다.
시간이 있다면 man errno
를 입력해서 102까지의 값들에 대한 설명도 읽어보세요.
다음을 참고하는 것도 괜찮습니다.
- errno(3) — Linux manual page (man7.org)
- [[/cmd/errno]]
0: Error 0
간단하게 [[/cmd/ls]]를 실행하고, 바로 뒤이어서 $?
를 출력해 보겠습니다.
$ ls >/dev/null ; echo $?
0
0
이 나오는군요. 정상 종료된 모양입니다.
;
는 명령어를 연결하는 구분자로 위의 명령은 사실 아래와 같은 것입니다.
$ ls >/dev/null
$ echo $?
0
그 외 몰라도 되는 것들?
rm
으로 존재하지 않는 파일을 삭제하려 해보면 종료 상태가 1
이 나옵니다.
$ rm qerqerqerqwerqer ; echo $?
rm: qerqerqerqwerqer: No such file or directory
1
ls
로 없는 파일을 찾아보려 하면 2
가 나옵니다.
$ ls aaasdf
gls: cannot access 'aaasdf': No such file or directory
$ echo $?
2
실행 권한이 없는 파일을 실행하면 126
이 나옵니다.
$ touch a.txt
$ ./a.txt
-bash: ./a.txt: Permission denied
$ echo $?
126
존재하지 않는 명령을 실행하면 127
이 나옵니다.
$ aaaasdfasdfa
-bash: aaaasdfasdfa: command not found
$ echo $?
127
실행중인 명령을 control c
로 강제로 종료하면 130
이 나옵니다.
$ yes >/dev/null
^C
$ echo $?
130
128 이후
128부터는 [[/study/os/signal]]{시그널}을 통해 프로세스가 종료될 때의 상태로 사용됩니다.
128에 시그널 번호를 더한 결과가 종료 상태가 된다고 생각하면 됩니다(128은 이진법으로 1000 0000
이니까 간단해서 선택된 것 같습니다).
다음은 sleep 10
으로 10초간 대기를 시킨 다음, ctrl + c
키를 입력해서 SIGINT(2)를 보낸 결과입니다.
$ sleep 10
^C
$ echo $?
130
128 + 2 = 130
이므로 종료 상태가 130
이 됩니다.
각 [[/study/os/signal]]{시그널}의 번호가 궁금하다면 man signal
을 입력하면 됩니다.
한편, C 프로그래밍 언어의 main
함수 시그니처를 기억하고 있다면 관례상 main
함수가 int
를 리턴하도록 작성되곤 한다는 것을 알고 있을 것입니다.
이때 main
함수가 리턴하는 int
가 바로 종료 상태값이 됩니다.
다음은 종료 상태로 0
(성공, 에러 없음)을 리턴하는 경우입니다.
int main(int argc, char *argv[]) {
return 0;
}
Java 또한 C 언어 계통의 언어이기 때문에 public static void main
역시도 C의 int main
과 비슷한 모양을 갖습니다.
public static void main(String[] args){
// 종료상태를 지정하지 않으면 0
}
Java로 작성한 애플리케이션에서 종료상태값을 수동으로 지정하려면 System.exit
를 사용합니다.
System.exit(1);
System.exit의 JavaDoc을 읽어보면
비정상 종료인 경우 0
이 아닌 값을 사용한다는 컨벤션도 명시하고 있습니다.