===================================================================================
1. 표준 입출력
linux에서는 프로그램 실행시 표준 입출력에 관한 파일디스크립터(fd)가 생성되게 된다.
기본적으로 표준 입력(0), 표준출력(1), 표준에러(2)로 설정된다.
그렇기 때문에 실제 코드상에서 fopen등으로 하나의 파일디스크립터를 얻게되면 대부분 3번부터 return한다.
표준입력 (stdin) 0 키보드
표준출력 (stdout) 1 모니터(터미널)
표준에러 (stderr) 2 모니터(터미널)
이와 같은 구조에서 입출력 재지정이란, in/out을 다른 곳으로 변경함을 의미하며. 일반적으로는 파일로 재지정이 가능하다.
2. redirection
linux에서 make > log 와 같은 구문을 본적이 있을텐데 이것이 바로 입출력 재지정을 의미한다.
재지정을 위한 연산자는 아래 표와 같다.
재지정구분 | 연산자 | 의미 | 사용예의 의미 |
---|
출력 | > | write | % 명령수행 > 기록할 파일이름 |
---|
>> | append | % 명령수행 >> 추가할 파일이름 |
---|
입력 | < | read | % 명령수행 < 읽어올 파일이름 |
---|
에러출력 | 2> | sh,ksh,bash | $ 명령수행 2> 기록할 오류파일이름 |
---|
>& | csh | % 명령수행 >& 기록할 오류파일이름 |
---|
예를 들기 위하여 간단한 shell script 하나를 작성해 보자.
-
- echo "STDIN START"
- ls -al
- echo "STDIN END"
- echo "STDERR START">&2
- ls e
- echo "STDERR END">&2
내용을 살펴보면 위의 코드는 ls -al와 ls k라는 명령을 수행한다.
ls -al의 경우 정상적으로 수행되지만, ls e라는 것은 정상적으로 수행되지 않고 오류를 출력할 것이다.
위 script를 일반적으로 수행해 보면 다음과 같이 나온다.
# ./a.sh
STDIN START
합계 12
drwxr-xr-x 2 jelee9 jelee9 4096 2010-05-31 12:53 .
drwxr-xr-x 31 jelee9 jelee9 4096 2010-05-31 12:52 ..
-rwxrwxrwx 1 jelee9 jelee9 104 2010-05-31 12:52 a.sh
STDIN END
STDERR START
ls: e에 접근할 수 없습니다.: No such file or directory
STDERR END
#
stdin과 stdout이 둘다 모니터로 출력되도록 되어 있으므로 두가지 모두 정상적으로 출력된다.
이제 redirection을 통하여 표준출력을 변경해 보도록 하자.
#./a.sh > stdin_log
STDERR START
ls: e에 접근할 수 없습니다.: No such file or directory
STDERR END
# cat stdin_log
STDIN START
합계 16
drwxr-xr-x 2 jelee9 jelee9 4096 2010-05-31 12:54 .
drwxr-xr-x 31 jelee9 jelee9 4096 2010-05-31 12:52 ..
-rwxrwxrwx 1 jelee9 jelee9 104 2010-05-31 12:52 a.sh
-rw-r--r-- 1 jelee9 jelee9 12 2010-05-31 12:54 stdin
STDIN END
#
STDIN의 경우에는 stdin_log 파일에만 출력되며 stderr만 모니터로 출력되는 것을 알 수 있다.
(./a.sh > stdin_log대신에 ./a.sh 1>stdin_log 모두 동일한 결과를 갖는다.)
이번엔 반대로 표준에러를 변경해 보도록 하자.
# ./a.sh 2>stderr_log
STDIN START
합계 16
drwxr-xr-x 2 jelee9 jelee9 4096 2010-05-31 12:54 .
drwxr-xr-x 31 jelee9 jelee9 4096 2010-05-31 12:52 ..
-rwxrwxrwx 1 jelee9 jelee9 104 2010-05-31 12:52 a.sh
-rw-r--r-- 1 jelee9 jelee9 12 2010-05-31 12:54 stdin
STDIN END
#cat stderr_log
STDERR START
ls: e에 접근할 수 없습니다.: No such file or directory
STDERR END
#
예상했던 대로 STDIN만 모니터로 출력되며 STDERR는 stderr_log 파일에 저장됨을 알 수 있다.
마지막으로 표준에러를 표준출력으로 변경해보자.
# (./a.sh 2>&1) > log
# cat log
STDIN START
합계 16
drwxr-xr-x 2 jelee9 jelee9 4096 2010-05-31 13:30 .
drwxr-xr-x 31 jelee9 jelee9 4096 2010-05-31 13:20 ..
-rwxrwxrwx 1 jelee9 jelee9 102 2010-05-31 13:26 a.sh
-rw-r--r-- 1 root root 12 2010-05-31 13:30 log
STDIN END
STDERR START
ls: e에 접근할 수 없습니다.: No such file or directory
STDERR END
#
표준에러(2)를 표준출력(1)으로 redirection한 후에 표준 출력을 log라는 파일에 저장하는 것이다.
이와같이 표준입출력을 재지정하면 원하는 출력을 파일로 저장하도록 할 수 있다.
대부분의 경우에는 build 시에 불필요한 log를 skip 하기 위하여 사용하는 경우가 많다.
(make > /dev/null과 같이 정상적인 build의 경우에는 화면 출력을 하지 않도록 설정)
3. tee 명령어
redirection의 경우에는 입출력의 방향을 변경할 수 있습니다. 그러나 불행하게도 redirection된 내용은 화면상에서 보이지 않게되는 문제점이 있다. 그래서 등장한 것이 tee 명령어 이다.
man page를 살펴보면, read from standard input and write to standard output and files 라고 적혀있다.
말 그대로 stdin을 stdin으로 출력과 동시에 파일에도 저장해주는 기능을 가지고 있다.
일단 한번 사용해 보도록 하자.
# ./a.sh | tee tee_log
STDIN START
합계 20
drwxr-xr-x 2 jelee9 jelee9 4096 2010-05-31 13:35 .
drwxr-xr-x 31 jelee9 jelee9 4096 2010-05-31 13:20 ..
-rwxrwxrwx 1 jelee9 jelee9 102 2010-05-31 13:26 a.sh
-rw-r--r-- 1 root root 334 2010-05-31 13:30 log
-rw-r--r-- 1 root root 12 2010-05-31 13:35 tee_log
STDIN END
STDERR START
ls: e에 접근할 수 없습니다.: No such file or directory
STDERR END
# cat tee_log
STDIN START
합계 20
drwxr-xr-x 2 jelee9 jelee9 4096 2010-05-31 13:35 .
drwxr-xr-x 31 jelee9 jelee9 4096 2010-05-31 13:20 ..
-rwxrwxrwx 1 jelee9 jelee9 102 2010-05-31 13:26 a.sh
-rw-r--r-- 1 root root 334 2010-05-31 13:30 log
-rw-r--r-- 1 root root 12 2010-05-31 13:35 tee_log
STDIN END
#
위와 같이 tee 명령을 사용하면 표준 출력의 경우 화면으로도 줄력되면서 동시에 tee_log 파일에도 기록되는 것을 알 수 있다.
실제로 제 경우에는 build 오류 메세지만 출력하기 위하여 stdin을 /dev/null로 보내도록 하였더니, 정작 error가 나왔을 때 어느 위치를 build 도중에 나온 것인지 모르는 경우가 발생하였다.
그래서 redirection과 tee 조합을 통하여 stdin은 파일에만 출력하도록, stderr의 경우에는 파일과 화면 출력을 동시에 하도록 사용하고 있다.
# (./a.sh >> log ) 2>&1 | tee -a log
STDERR START
ls: e에 접근할 수 없습니다.: No such file or directory
STDERR END
# cat log
STDIN START
합계 16
drwxr-xr-x 2 jelee9 jelee9 4096 2010-05-31 13:41 .
drwxr-xr-x 31 jelee9 jelee9 4096 2010-05-31 13:20 ..
-rwxrwxrwx 1 jelee9 jelee9 102 2010-05-31 13:26 a.sh
-rw-r--r-- 1 root root 12 2010-05-31 13:41 log
STDIN END
STDERR START
ls: e에 접근할 수 없습니다.: No such file or directory
STDERR END
#
이처럼 redirection과 tee의 조합을 사용하여 약간의 개발의 편리를 추구할 수 있지 않을 까?
ps. 회사에서 일반 log를 모조리 출력하지 않으면,
오래 걸리는 build를 걸어 놨을 경우에...
일 안하고 멍때리는 사람으로 오해받을 소지 많으니 주의할것. ㅡ,,ㅡ;;
출처 - http://www.leejongeun.com/tc/entry/Linux-%ED%91%9C%EC%A4%80%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%9E%AC%EC%A7%80%EC%A0%95