youngfromnowhere

[Linux Shell]Bash Shell의 file descriptor. 본문

Linux Shell

[Linux Shell]Bash Shell의 file descriptor.

곽일땡 2022. 10. 31. 18:51
bash shell script 공부중 file descriptor에 대해 생긴 의문과 그 해결
스크립트 파일(파일명 script)에 다음과 같이 적는다

 

#!/bin/bash
echo "Hello World" >&2​

 

그 후 커맨드라인에서 해당 파일을 다음과 같이 실행시킨다
 
$ ./script 2> outputfile
이러면 "Hello World"라는 문자열은 모니터에 출력되지 않고 file descriptor 2를 통하여 outputfile로 전달된다.
이해하는데 전혀 어렵지 않다. 마치 file descriptor 2라는 오브젝트가 있고 문자열이 그곳을 거쳐 커맨드에서 지정한 파일로 전달되는 것처럼 이해하면 된다.
그런데 exec 명령을 이용하여 리다이렉트를 왔다리갔다리 시킬때 혼란이 온다.
파일 script에 다음과 같이 적는다.
 
#!/bin/bash
exec 3>&1
exec 1>outputfile
echo "Hello World 1"
echo "Hello World 2"
exec 1>&3
echo "Hello World 3"
 
첫 두줄을 보면, 3을 1에 연결하고 1을 outputfile에 연결했으니 3이 outputfile에 연결됐다고 이해하기 쉽다. 하지만 그렇지 않다.
3은 '현재 1이 가리키는 곳'인 모니터로 연결돼고, 1만 outputfile에 연결된다. 따라서 1로 출력되는 "Hello World 1", "Hello World 2"는 outputfile에 전달된다.
그런다음 1이 3에 연결되고, 그 다음 "Hello World 3"이 출력되므로 이 문장은 첫 줄에서 '현재 3이 가리키는' 모니터로 출력된다.
뭔가 이상하다고 느껴진다. 첫번째 사례에서는 'file desciptor'라는 오브젝트를 상정하고 'A에 B를 연결' 'B에 C를 연결'하면 A는 C로 연결된다고 이해하면 되는데 두번째 스크립트의 첫 두줄에는 그 논리가 적용되지 않는다.
이 모순은 우리가 인간 입장에서 '스크립트가 먼저, 커맨드라인 명령은 나중'이라고 생각하기 때문에 발생한다.
사실 컴퓨터 입장에선 '커맨드가 먼저'고, 그 다음에 스크립트 파일을 한줄씩 읽어들이게 된다.
즉 첫번째 스크립트에서, Hello World를 2로 보낸 다음 2를 outputfile로 보낸게 아니라,
2가 가리키는 곳을 먼저 outputfile로 만들고 스크립트에서 Hello World를 2로 보낸 것이다.
즉 컴퓨터는 언제나 '파일 디스크립터가 현재 가리키는 곳'으로 리다이렉트 하므로, 내가 원하는 곳으로 출력을 내보내기 위해서는 파일디스크립터에 내가 원하는 출력 장소를 '미리' 할당(저장?) 해놔야 한다. 그리고 '커맨드 라인에서의 리다이렉트'는, 사람 입장에선 나중에 입력하는 명령이지만 컴퓨터가 인지하는 첫번째 리다이렉트가 되는 것이다.