`command 1> file.txt 2> file.txt`의 동작이`command 1> file.txt 2> & 1`과 다른 이유는 무엇입니까?


20

stdout과 stderr을 동일한 파일로 리디렉션하려면 command 1>file.txt 2>&1, 또는 을 사용하여 수행 할 수 있습니다 command &>file.txt. 그러나 왜 command 1>file.txt 2>file.txt위의 두 명령 과 다른 동작을 합니까?

다음은 확인 명령입니다.

$ cat redirect.sh
#!/bin/bash

{ echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file.txt 2>&1
{ echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file1.txt 2>file1.txt
{ echo -e "error" 1>&2 && echo -e "output\noutput"; } 1>file2.txt 2>file2.txt
{ echo -e "output" && echo -e "error\nerror" 1>&2; } 1>file3.txt 2>file3.txt
{ echo -e "error\nerror" 1>&2 && echo -e "output"; } 1>file4.txt 2>file4.txt

$ ./redirect.sh

$ echo "---file.txt---"; cat file.txt;\
echo "---file1.txt---"; cat file1.txt; \
echo "---file2.txt---"; cat file2.txt; \
echo "---file3.txt---"; cat file3.txt; \
echo "---file4.txt----"; cat file4.txt;
 ---file.txt---
output
output
error
---file1.txt---
error

output
---file2.txt---
output
output
---file3.txt---
error
error
---file4.txt----
output
rror

결과가 표시되는 한, 두 번째 에코 문자열을 실행할 때 첫 번째 에코 문자열을 덮어 쓰는 것처럼 보이지만 그 command 1>file.txt 2>file.txt이유는 알 수 없습니다. (어딘가에 참조가 있습니까?)

답변:


43

두 가지를 알아야합니다.

  • 프로세스의 응용 프로그램 모드 측에 알려진 열린 파일 디스크립터 는 열린 파일 의 인스턴스 인 파일 설명으로 알려진 내부 커널 오브젝트를 참조 합니다. 파일 당 여러 파일 설명과 파일 설명을 공유하는 여러 파일 설명자가있을 수 있습니다.
  • 현재 파일 위치 (A)의 속성 인 파일의 설명 . 따라서 여러 파일 디스크립터가 단일 파일 설명에 맵핑되는 경우 모두 동일한 현재 파일 위치를 공유하며 이러한 파일 디스크립터 중 하나를 사용하여 파일 위치를 변경하면 다른 모든 파일 디스크립터에 영향을줍니다.

    이러한 변화는 호출 프로세스에 의해 제정된다 read()/ readv(), write()/ writev(), lseek()그리고 그와 같은 시스템 호출을. echo명령 통화 write()/ writev()물론.

그래서 이런 일이 발생합니다 :

  • command 1>file.txt 2>&1쉘은 파일을 한 번만 열기 때문에 하나의 파일 설명 만 작성합니다. 쉘 차종 모두 표준 출력과 표준 에러 파일 기술자는 단일 파일 설명에. 그것은 중복 표준 오류 위에 표준 출력을. 따라서 두 파일 디스크립터를 통한 쓰기는 공유 된 현재 파일 위치를 이동합니다. 각 쓰기는 이전 쓰기 후에 공통 파일 설명을 따릅니다. 보시 echo다시피 명령 결과가 서로 덮어 쓰지 않습니다.
  • command 1>file.txt 2>file.txt쉘이 두 개의 명시적인 재 지정에 응답하여 동일한 파일을 두 번 열기 때문에 두 개의 파일 설명을 작성 합니다. 표준 출력 및 표준 오류 파일 디스크립터는 두 개의 다른 파일 설명에 맵핑 된 다음 동일한 단일 파일에 맵핑됩니다. 두 파일 설명은 완전히 독립적 인 현재 파일 위치를 가지며 각 쓰기는 동일한 파일 설명에서 즉시 이전 쓰기로 진행됩니다. 결과를 보면 알 수 있듯이 하나를 통해 작성된 내용은 다른 순서를 통해 기록 된 내용을 순서에 따라 다양한 방식으로 덮어 쓸 수 있습니다.

추가 자료


1
이어야한다 열려있는 파일 설명 이 아닌 파일 설명 . 파일 자체보다 파일이 어떻게 열린 지에 대한 기록입니다. 이것이 POSIX, Linux, Solaris 및 GNU 문서에서 사용되는 용어입니다.
Stéphane Chazelas

16

를 사용 >하면 파일을 덮어 쓰게됩니다. stdout과 stderr이 두 가지 다른 작업으로 파일에 쓰는 중이므로 마지막으로 쓰는 작업이 첫 번째 작업을 덮어 씁니다.

넌 할 수있어:

command 1>>file.txt 2>>file.txt

또는

command &>file.txt bash v4 이상 만.

>> 이전 작업의 출력을 대체하지 않도록 파일을 추가하도록 지시합니다.

&> 쓰기 쉬운 방법입니다 2>&1


2
이유는 무엇입니까 ls 1>&0그리고 ls 0>&0여전히 LS의 출력을 보여?
Yvain

사용하는 것이 놀랍습니다 >>. 이것이 독립 오프셋을 가진 두 파일 설명의 문제가없는 이유는 무엇입니까? @JdeBP, 알고 있습니까? 추가 모드에서 파일을 여는 것은 쓰기 모드에서 열고 최종 위치를 찾은 다음 추가 탐색을 허용하지 않는 것과 같습니다.
JoL September

4
@jlmg : 추가 모드 파일은 검색 가능하지만 모든 쓰기에는 끝에 암시 적 검색이 붙습니다. 그 암시 적 탐색이 원자인지 아닌지는 명확하지 않습니다.
Kevin

1
그것은 전적으로 후속 질문에 달려 있습니다. 이와 관련이있는 것은 답변이 불완전하다는 것을 나타냅니다. 그리고 사람들이 완전한 답을 알고 싶어하지 않고 후속 질문을 찾지는 않을 것입니다. 따라서 그러한 질문에 대한 후속 조치는 정보를 복제하는 답변을 가질 가능성이 높으므로 중복으로 폐쇄됩니다.
trlkly

1
@Kevin은 POSIX 호환 파일 시스템에서 암시 적 O_APPEND 찾기가 원자 적입니다. 즉, 모든 파일 시스템이 관련 시맨틱을 올바르게 구현하는 것은 아닙니다. 예를 들어 NFS (최소 v3 및 이전-v4에서는 명확하지 않음)에는 해당 지원이 유선 프로토콜에 포함되어 있지 않으므로 서버는 클라이언트가로 파일을 열 었는지 알 수 없습니다 O_APPEND.
Charles Duffy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.