당신은 이미 아주 좋은 답변을 받았습니다. 여기에 관련된 두 가지 다른 개념이 있다는 것을 강조하겠습니다.
배경 : 파일 디스크립터 대 파일 테이블
파일 디스크립터는 프로세스의 파일 디스크립터 테이블에있는 인덱스 인 숫자 0 ... n입니다. 관습에 따라 STDIN = 0, STDOUT = 1, STDERR = 2 ( STDIN
여기서 용어 등은 일부 프로그래밍 언어 및 매뉴얼 페이지에서 관례에 의해 사용되는 기호 / 매크로 임), STDIN이라는 실제 "객체"는 없습니다. 이 논의의 목적에서 STDIN 은 0 등입니다.)
해당 파일 디스크립터 테이블 자체에는 실제 파일에 대한 정보가 포함되어 있지 않습니다. 대신 다른 파일 테이블에 대한 포인터를 포함합니다. 후자는 실제 실제 파일 (또는 블록 장치 또는 파이프 또는 Linux가 파일 메커니즘을 통해 처리 할 수있는 모든 것)에 대한 정보와 추가 정보 (즉, 읽기 또는 쓰기 용 여부)를 포함합니다.
따라서 셸에서 >
또는 <
셸 을 사용 하면 해당 파일 디스크립터의 포인터를 다른 것으로 가리 키기 만하면됩니다. 이 구문은 2>&1
단순히 설명자 2를 1이있는 곳을 가리 킵니다. > file.txt
단순히 file.txt
쓰기 위해 열리고 STDOUT (파일 설명자 1)이이를 가리 키도록합니다.
다른 장점이 있습니다 2>(xxx)
(예 : 실행중인 새 프로세스 xxx
만들기, 파이프 만들기, 새 프로세스의 파일 설명자 0을 파이프의 읽기 끝에 연결하고 원래 프로세스의 파일 설명자 2를 파이프).
이것은 또한 쉘 이외의 다른 소프트웨어에서 "파일 핸들 매직"의 기초입니다. 예를 들어, Perl 스크립트 dup
에서 STDOUT 파일 디스크립터를 다른 (임시) 파일 디스크립터에 연결 한 후 STDOUT을 새로 작성된 임시 파일로 다시 열 수 있습니다. 이 시점부터는 자신의 Perl 스크립트 및system()
해당 스크립트의 모든 호출 에서 나온 모든 STDOUT 출력 이 해당 임시 파일에있게됩니다. 완료되면 dup
STDOUT을 저장 한 임시 디스크립터로 재 저장할 수 있으며 이전과 동일합니다. 그 동안 임시 디스크립터에 쓸 수도 있으므로 실제 STDOUT 출력이 임시 파일로 이동하는 동안 실제 STDOUT (일반적으로 사용자)으로 실제로 출력 할 수 있습니다 .
대답
위에 주어진 배경 정보를 질문에 적용하려면 :
셸은 어떤 순서로 명령과 스트림 리디렉션을 실행합니까?
좌에서 우로.
<command> > file.txt 2>&1
fork
새로운 과정에서
file.txt
파일 디스크립터 1 (STDOUT)에서 포인터를 열고 저장하십시오.
- STDERR (파일 설명자 2)을 fd 1이 지금 가리키는 모든 것을 가리 킵니다 (이것은
file.txt
물론 이미 열려 있습니다).
exec
그만큼 <command>
이것은 stderr을 stdout으로 먼저 리디렉션 한 다음 결과 stdout이 file.txt로 리디렉션됩니다.
단지이 있다면이 나을 하나 개의 테이블 만으로는 두 가지가 있습니다 위의 설명했다. 파일 디스크립터가 재귀 적으로 서로를 가리 키지 않으므로 "STDERR을 STDOUT으로 경로 재 지정"하는 것은 의미가 없습니다. 올바른 생각은 "STDERR이 STDOUT이 가리키는 곳을 가리 킵니다"입니다. 나중에 STDOUT을 변경하면 STDERR은 그대로 유지되며 STDOUT에 대한 추가 변경과 함께 마술처럼 진행되지 않습니다.