쉘은 항상 기본적으로 표준입력(stdin, 키보드), 표준출력(stdout, 스크린), 표준에러(stderr, 스크린에 뿌려질 에러 메세지) "파일들"을 열어 놓습니다. 이 파일들을 포함해서 열려 있는 어떤 파일이라도 재지향 될 수 있습니다. 재지향이란 간단히 말해서 파일, 명령어, 프로그램, 스크립트, 심지어는 스크립트 속의 코드 블럭의 출력을 낚아 채서 다른 파일, 명령어, 프로그램, 스크립트의 입력으로 보내는 것입니다.
열려 있는 파일 각각은 파일 디스크립터(file descriptor)를 할당 받습니다. [1] 표준입력, 표준출력, 표준에러에 해당하는 파일 디스크립터는 각각 0, 1, 2 입니다. 추가적으로 열리는 파일을 위해서 3부터 9까지의 파일 디스크립터가 남겨져 있습니다. 종종, 이 추가적인 파일 디스크립터들중의 하나를 표준입력, 표준출력, 표준에러로 할당해서 임시적인 중복된 링크로 쓰는 것이 유용할 때가 있습니다. 이런 방법을 쓰면 아주 복잡한 재지향이나 파일 디스크립터를 뒤죽 박죽 사용했을 때, 아주 간단하게 원래대로 복구시켜 줍니다
|
여러개의 입출력 재지향과 파이프를 하나의 명령어 줄에서 같이 쓸 수 있습니다.
command < input-file > output-file command1 | command2 | command3 > output-file |
여러개의 출력 스트림이 한 파일로 재지향 될 수도 있습니다.
ls -yz >> command.log 2>&1 # "ls"의 잘못된 옵션인 "yz"의 결과를 "command.log"로 저장합니다. # 표준에러가 파일로 재지향 됐기 때문에 어떤 에러 메세지라도 그 파일에 저장됩니다. |
- n<&-
n번 입력 파일 디스크립터를 닫아 줍니다.
- 0<&-, <&-
표준입력을 닫아 줍니다.
- n>&-
n번 출력 파일 디스크립터를 닫아 줍니다.
- 1>&-, >&-
표준출력을 닫아 줍니다.
자식 프로세스는 열려 있는 파일 디스크립터를 상속 받는데 이것 때문에 파이프가 동작합니다. 파일 디스크립터가 상속되길 바라지 않는다면 그 파일 디스크립터를 닫으면 됩니다.
# 파이프로 표준에러만 재지향 하기. exec 3>&1 # 표준출력의 현재 "값"을 저장. ls -l 2>&1 >&3 3>&- | grep bad 3>&- # 'ls'와 'grep'을 위해 3번 파일 디스크립터를 닫고, exec 3>&- # 이제, 스크립트 나머지 부분을 위해 닫습니다. # Thanks, S.C. |
I/O 재지향 ==================================================================== [root@fw ~]# ls -l /proc/12896/fd total 0 lrwx------ 1 root root 64 May 9 10:14 0 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 1 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 2 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 255 -> /dev/pts/2 [root@fw ~]# tty /dev/pts/2 [root@fw ~]# ps PID TTY TIME CMD 12896 pts/2 00:00:00 bash 13048 pts/2 00:00:00 ps -- filetest.c -- #include <stdio.h> // fopen, fclose, fprintf #include <unistd.h> // sleep int main() { FILE *fp; fp = fopen("/tmp/filetest.txt", "a"); fprintf(fp, "Hello World \n"); sleep(100); fclose(fp); return 0; } -- filetest.c -- -- 실행결과 -- # ./filetest& # ls -l /proc/13122/fd total 0 lrwx------ 1 root root 64 May 9 11:40 0 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:40 1 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:40 2 -> /dev/pts/2 l-wx------ 1 root root 64 May 9 11:40 3 -> /tmp/filetest.txt -- 실행결과 -- > 표준출력을 파일로 재지향. 파일이 없으면 새로 만들고, 있다면 덮어 쓴다. 덮어쓴다는 얘기는 기존의 내용을 삭제하고 새로운 내용이 들어간다. # ls -ld /etc/passwd -rw-r--r-- 1 root root 2073 May 8 21:44 /etc/passwd # ls -ld /etc/passwd > passwd.txt # cat passwd.txt -rw-r--r-- 1 root root 2073 May 8 21:44 /etc/passwd >> 표준출력을 파일로 재지향. 파일이 없으면 새로 만들고, 있으면 파일 끝에 덧붙인다. # ls -ld /etc/passwd >> passwd.txt # cat passwd.txt -rw-r--r-- 1 root root 2073 May 8 21:44 /etc/passwd -rw-r--r-- 1 root root 2073 May 8 21:44 /etc/passwd # ls -ld /etc/passwd >> passwd.txt # cat passwd.txt -rw-r--r-- 1 root root 2073 May 8 21:44 /etc/passwd -rw-r--r-- 1 root root 2073 May 8 21:44 /etc/passwd -rw-r--r-- 1 root root 2073 May 8 21:44 /etc/passwd # ls -ld /etc/passwd > passwd.txt # cat passwd.txt -rw-r--r-- 1 root root 2073 May 8 21:44 /etc/passwd
- 정상출력(1) 으로 재지향 # echo 12345 1> a.txt # cat a.txt 12345 # echo 1234567890 2> a.txt 1234567890 # cat a.txt # # # echo 1234567890 1234567890 # echo $? 0 - 비정상출력(2) 으로 재지향 # afjaksdf -bash: afjaksdf: command not found # eco $? -bash: eco: command not found # afjaksdf -bash: afjaksdf: command not found # echo $? 127 # afjaksdf 1> a.txt -bash: afjaksdf: command not found # cat a.txt # afjaksdf 2> a.txt # cat a.txt -bash: afjaksdf: command not found - IO 재지향을 이용한 파일쓰기 # echo 0123456789 > File # cat File 0123456789 # exec 3<>File # ls -l /proc/$$/fd total 0 lrwx------ 1 root root 64 May 9 10:14 0 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 1 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 2 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 255 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:58 3 -> /root/File # read -n 4 <&3 # cat File 0123456789 # echo -n . >&3 # cat File 0123.56789 # exec 3>&- # ls -l /proc/$$/fd total 0 lrwx------ 1 root root 64 May 9 10:14 0 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 1 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 2 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 255 -> /dev/pts/2 # cat File 0123.56789 test.c /*----- fname : test.c -----*/ #include <stdio.h> #include <unistd.h> int main() { sleep(100); return 0; } [root@fw ~]# ./test > /dev/null 2>&1 & [1] 13214 [root@fw ~]# ls -l /proc/13214/fd total 0 lrwx------ 1 root root 64 May 14 11:18 0 -> /dev/pts/4 l-wx------ 1 root root 64 May 14 11:18 1 -> /dev/null l-wx------ 1 root root 64 May 14 11:18 2 -> /dev/null [root@fw ~]# [1]+ Done ./test > /dev/null 2>&1 [root@fw ~]# [root@fw ~]# [root@fw ~]# [root@fw ~]# ./test 2> /dev/null >&2 & [1] 13216 [root@fw ~]# ls -l /proc/13216/fd total 0 lrwx------ 1 root root 64 May 14 11:21 0 -> /dev/pts/4 l-wx------ 1 root root 64 May 14 11:21 1 -> /dev/null l-wx------ 1 root root 64 May 14 11:21 2 -> /dev/null [root@fw ~]# ./test 2> /dev/null 1>&2 & [2] 13218 [root@fw ~]# ls -l /proc/13218/fd total 0 lrwx------ 1 root root 64 May 14 11:21 0 -> /dev/pts/4 l-wx------ 1 root root 64 May 14 11:21 1 -> /dev/null l-wx------ 1 root root 64 May 14 11:21 2 -> /dev/null - 파일디스크립터 닫기 pts/0# ps PID TTY TIME CMD 13232 pts/4 00:00:00 bash 13311 pts/4 00:00:00 ps pts/0# ls -l /proc/$$/fd total 0 lrwx------ 1 root root 64 May 9 10:14 0 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 1 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 2 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 255 -> /dev/pts/2 pts/1# ls -l /proc/13232/fd total 0 lrwx------ 1 root root 64 May 9 10:14 0 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 1 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 2 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 255 -> /dev/pts/2 pts/0# exec 1<&- pts/1# ls -l /proc/13232/fd total 0 lrwx------ 1 root root 64 May 9 10:14 0 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 2 -> /dev/pts/2 lrwx------ 1 root root 64 May 9 11:27 255 -> /dev/pts/2pts/0# ps pts/0# ls pts/0# vi .bash_logout -- .bash_logout -- sleep 50 clear -- .bash_logout -- pts/0# ps PID TTY TIME CMD 13323 pts/2 00:00:00 bash 13355 pts/2 00:00:00 ps pts/0# exec 0<&- pts/1# ls -l /proc/13323/fd total 0 lrwx------ 1 root root 64 May 14 11:30 0 -> /dev/pts/2 lrwx------ 1 root root 64 May 14 11:31 1 -> /dev/pts/2 lrwx------ 1 root root 64 May 14 11:31 2 -> /dev/pts/2 lrwx------ 1 root root 64 May 14 11:31 255 -> /dev/pts/2 pts/1# ls -l /proc/13323/fd total 0 lrwx------ 1 root root 64 May 14 11:31 1 -> /dev/pts/2 lrwx------ 1 root root 64 May 14 11:31 2 -> /dev/pts/2 lrwx------ 1 root root 64 May 14 11:31 255 -> /dev/pts/2====================================================================
'Linux > 쉘스크립트' 카테고리의 다른 글
변수 타입 지정: declare 나 typeset (0) | 2015.05.14 |
---|---|
매개변수 치환(Parameter Substitution) (0) | 2015.05.14 |
문자열 조작 (0) | 2015.05.13 |
내부 변수(Internal Variables) (0) | 2015.05.12 |
until과 위치 매개변수 사용 (0) | 2015.05.11 |