리눅스/유닉스의 콘솔/터미널의 bash 쉘 등에서는 재지향(Redirection)이라는 방법으로, 각종 명령어 출력 결과를 파일로 저장할 수 있습니다.

예를 들어 ls 명령의 출력 결과를, 연필로 옮겨쓰는 대신에

ls > out.txt

라고 하면 out.txt 라는 파일로 ls 명령의 결과가 간단히 저장됩니다. ls뿐 아니라 다른 모든 명령들도 마찬가지입니다.

> 이런 기호는, 글자들의 출력 방향을 화면이 아닌, 파일 같은 다른 데로 전환시키는 것입니다.


에러 메시지까지 파일로 저장하는 방법


그런데 위의 재지향 방법으로는 에러 메시지 출력은 저장되지 않습니다. 에러 메세지까지 파일로 저장되어 버리면, 에러가 났는지 알 수 없기 때문입니다. 기술적으로 말하자면, 일반 문자열은 "표준 출력(Standard Output)"으로 출력되고, 에러는 "표준 에러 출력(Standard Error)"으로 출력되기에 재지향이 안되는 것입니다.

에러까지 재지향하여 파일로 저장하는 방법이 있습니다.

ls ewyrsyrwyy &> out.txt

이렇게 &> 기호로 재지향하면 됩니다. ewyrsyrwyy 라는 이름의 파일이 없을 것이기에, ls 에서 그런 파일을 찾을 수 없다(No such file or directory)고 에러가 납니다. 그 에러 메시지가 out.txt 라는 파일로 저장됩니다.


출처 - http://mwultong.blogspot.com/2006/10/linux-unix-output-to-file.html


===================================================================================


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 하나를 작성해 보자.

  1. #!/bin/sh  
  2. echo "STDIN START"  
  3. ls -al  
  4. echo "STDIN END"  
  5. echo "STDERR START">&2  
  6. ls e  
  7. 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

'System > Linux' 카테고리의 다른 글

linux - 환경변수  (0) 2012.07.17
linux - 백그라운드 실행 & 과 nohup의 차이  (0) 2012.07.17
linux - scp 사용법  (0) 2012.07.16
linux - gcc와 make  (0) 2012.07.16
centos - python 2.6.x 설치  (1) 2012.07.13
Posted by linuxism
,