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
왜 이런 일이 발생하는지 모르겠습니다. (참고할 수 있는 곳이 있을까요?)
답변1
다음 두 가지를 알아야 합니다.
- 열린파일 설명자프로세스의 애플리케이션 모드 측은 다음과 같은 내부 커널 개체를 참조하는 것으로 알려져 있습니다.파일 설명, 파일을 여는 인스턴스입니다. 각 파일에는 여러 파일 설명이 있을 수 있으며 여러 파일 설명자가 파일 설명을 공유합니다.
- 이것현재 파일 위치의 속성이다파일 설명. 따라서 여러 파일 설명자가 단일 파일 설명에 매핑되는 경우 모두 동일한 현재 파일 위치를 공유하며 이러한 파일 설명자 하나를 사용하여 파일 위치를 변경하면 다른 모든 파일 설명자에 영향을 줍니다.
이러한 변경 사항은
read()
/readv()
,write()
/writev()
등 의 시스템 호출을 호출하는lseek()
프로세스를 통해 구현 됩니다.echo
물론 이 명령은write()
/를 호출합니다.writev()
그래서 일어나는 일은 다음과 같습니다:
command 1>file.txt 2>&1
쉘은 파일을 한 번만 열기 때문에 하나의 파일 설명만 생성됩니다. 쉘이 만든다둘 다표준 출력 및 표준 오류 파일 설명자는 이 단일 파일 설명에 매핑됩니다. 그것중복표준 출력은 표준 오류로 전환됩니다. 따라서 두 파일 설명자를 통해 쓰면 공유의 현재 파일 위치가 이동됩니다. 각 쓰기는 이전에 공통 파일 설명자에 쓴 후에 발생합니다. 보시다시피, 명령의 결과는echo
서로 덮어쓰이지 않습니다.command 1>file.txt 2>file.txt
만들다둘두 번의 명시적인 리디렉션에 대한 응답으로 쉘이 동일한 파일을 두 번 열기 때문에 파일 설명입니다. 표준 출력 및 표준 오류 파일 설명자는 두 개의 서로 다른 파일 설명에 매핑되며, 이는 다시 동일한 파일에 매핑됩니다. 두 파일 설명은 완전히 독립적인 현재 파일 위치를 가지며 각 쓰기는 동일한 파일 설명에 대한 이전 쓰기를 즉시 실행합니다. 보시다시피, 결과적으로 한 쪽을 통해 쓰여진 내용은 쓰기를 수행하는 순서에 따라 다양한 방식으로 다른 쪽을 통해 쓰여진 내용을 덮어쓸 수 있습니다.
추가 읽기
답변2
Use는 >
파일을 덮어쓰도록 지시합니다. 두 가지 다른 작업으로 stdout 및 stderr을 파일에 기록하므로 마지막 쓰기가 첫 번째 쓰기를 덮어씁니다.
넌 할 수있어:
command 1>>file.txt 2>>file.txt
또는
command &>file.txt
bash v4 이상만 가능합니다.
>>
이전 작업의 출력을 대체하지 않도록 파일을 추가하도록 지시합니다.
&>
그냥 쓰는 방법이 더 간단해요2>&1