이 스크립트를 설명해주세요(출처:ABSG. 장. 20):
exec 3>&1 # Save current "value" of stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&- # Close fd 3 for 'grep' (but not 'ls').
# ^^^^ ^^^^
exec 3>&- # Now close it for the remainder of the script
현재 나는 그것이 어떻게 작동하는지 상상합니다.
- fd/3 출력을 stdout에 연결하는 스크립트
- 파이프는 stdout을
ls
stdin에 연결합니다grep
(두 프로세스 모두 fd/3을 상속함). ls
stderr를 stdout으로 리디렉션- stdout이
ls
fd/3으로 변경됩니다(따라서 프로세스에서grep
더 이상 출력이 없고 오류만 발생함).ls
- fd/3이 닫혔습니다.
ls
이것이 정확한 리디렉션 순서입니까?
ls
if에서 오류 출력이 표시되지 않고 fd/3에 의해 리디렉션된 stdout을 닫는 이유를 이해할 수 없습니다 .
grep
fd/3 종료 process() 의 목적은 무엇입니까 grep bad **3>&-**
?
답변1
파일 설명자를 파일을 값으로 받아들이는(또는 I/O 스트림이라고 부르는) 변수로 생각하고 표시되는 순서가 평가되는 순서대로 생각하면 도움이 됩니다.
위의 예에서는 다음과 같은 일이 발생합니다.
1) 스크립트는 다음으로 시작합니다(상속되지 않는 한 기본적으로).
fd/0 = stdin # that's the keyboard
fd/1 = stdout # that's the screen
fd/2 = stderr # the screen again, but different stream
2) 이 exec
명령은 새로운 변수를 선언하고 값을 할당하는 것으로 해석됩니다.
fd/3 = fd/1 # same as stdout
이제 두 파일 설명자의 값은 stdout입니다. 즉, 둘 다 화면에 인쇄하는 데 사용할 수 있습니다.
3) ls
열려 있는 모든 파일 설명자를 실행하고 상속하기 전에 다음 설정이 수행됩니다.
ls.fd/1 = grep.fd/0 # pipe gets precedence, ls.fd/1 writes to grep.stdin
ls.fd/2 = ls.fd/1 # ls.fd/2 writes to grep.stdin
ls.fd/1 = ls.fd/3 # ls.fd/1 writes to stdout
ls.fd/3 = closed # fd/3 will not be inherited by `ls`
fd/3의 목적은 표준 출력 값을 fd/1로 반환할 수 있을 만큼 오랫동안 유지하는 것입니다. 이제 ls
fd/1로 전송된 모든 내용은 stdin 대신 stdout으로 전송됩니다 grep
.
순서가 중요합니다. 예를 들어 ls -l >&3 2>&1 3>&-
ls.fd/2를 실행하면 표준 입력 대신 표준 출력에 기록됩니다 grep
.
4) fd/3 for grep
는 닫혀 있고 상속되지 않습니다. 어쨌든 사용될 것입니다. grep
오류 메시지만 필터링할 수 있습니다.ls
ABSG에 제공된 예는 가장 도움이 되지 않을 수 있으며 ""grep"에 대해 fd 3을 닫습니다(그러나 "ls"는 아님).”는 약간 오해의 소지가 있으므로 다음과 같이 읽을 수 있습니다.ls의 경우 설정을 해제하기 전에 ls.fd/3 값을 ls.fd/1에 전달하여 닫히지 않도록 합니다.".