메뉴 건너뛰기

Hodol's Blog

Documents 쉘 리다이렉터

2016.07.31 16:09

Hodol 조회 수:136

쉘에서 리다이렉팅
쉘에서 로그를 뽑아서 파일로 저장할 때, 다음과 같은 명령을 쓴다.
$ some_command > bar.txt
위 명령의 작동은 some_command의 출력을 bar.txt로 넣어주는 것으로 이해했었는데 이런 식으로 알고 있으면 다음의 명령의 작동 방식을 이해하기가 힘들어 진다.
$ some_command > /dev/null 2>&1
여기서 &1은 표준출력 장치를 가리키기 위한 디크립터이고 이름이 1인 파일과 구분하기 위해 &를 붙여준다. 아무튼, 앞서 이해한 방식으로 들이대면 위 명령은 some_command의 표준 출력을 /dev/null 파일(사실은 블랙홀 장치)로 넣고, >명령(?)의 표준 에러를 다시 표준 출력으로 표시하라는 명령으로 생각할 수 있다. 하지만 > 명령의 표준 에러는 원래 없으므로 아무 것도 표시되지 않는다...라고 생각할 수 있다. 그러나 다음 실험은 이러한 생각에 맞지 않은 결과를 보여준다.
// test.c
#include <stdio.h>
int main () {
    fprintf(stdout,"Hello, STDOUT!\n");
    fprintf(stderr,"Hello, STDERR!\n");
    return 0;
}
위의 C 코드를 다음과 같이 컴파일하여 실행해 보자.
$ gcc -o test test.c
$ ./test > test.txt 2>&1
$ cat test.txt
위 명령을 실행하면 다음과 같은 결과를 얻는다.
Hello, STDERR!
Hello, STDOUT!
$
표준 출력과 표준 에러의 순서가 바뀐 것은 둘째치고 표준 출력과 표준 에러 둘 다 한 파일에 기록이 되었다. 이게 무슨 일인가? 표준 출력만 파일에 기록되고 표준 에러는 화면에만 출력될거란 예상과는 다른 결과를 보여준다. 이는 >를 쉘 명령의 옵션으로 이해해야 한다. 즉, >를 하나의 명령이 아닌, 쉘에서 실행된 모든 명령에 대해 그 입출력을 다시 설정해주는 전역 옵션으로 이해하는 것이다.
$ ./test > test.txt 2>&1
위 명령은 다음 명령과 같다.
$ ./test 1>test.txt 2>&1
풀이하자면 ./test의 명령을 실행하는데, 이 명령의 표준 출력(1)을 test.txt로 설정하고 표준 에러(2)는 표준 출력(1)으로 설정하고 실행하라는 뜻이다. 따라서 ./test의 표준 출력은 test.txt로 들어가도록 설정되어 있고, 표준 에러는 표준 출력으로 들어가도록 설정되어 있는데 앞서 표준 출력은 미리 test.txt로 설정되어 있으므로 표준 에러도 파일에 기록된다. 표준 입출력 디크립터가 화면이라는 장치로 고정된 것이 아니며, 이 표준 입출력 장치를 사용자 임의대로 설정하는 쉘의 옵션이 리다이렉터인 것이다. Redirect라는 단어가 무엇을 의미하는지를 생각해본다면 이해하는데 도움이 된다.