Bash 매뉴얼의 리디렉션 섹션에 있는 오타입니까?

Bash 매뉴얼의 리디렉션 섹션에 있는 오타입니까?
Note that the order of redirections is significant.  For example, the command

          ls > dirlist 2>&1

   directs both standard output and standard error to the file dirlist, 
   while the command

          ls 2>&1 > dirlist

   directs  only  the  standard  output  to  file  dirlist,  because the 
   standard error was duplicated from the standard output before the standard
   output was redirected to dirlist.

이제 마지막 부분이 나를 혼란스럽게 합니다. 이 경우 표준 오류는 터미널에 인쇄되고 STDOUT은 디렉터리 목록 파일로 이동됩니다. 그런 일이 발생하지만 매뉴얼을 이해하는 것은 아닙니다.

"표준 출력이 디렉토리 목록으로 리디렉션된 후 표준 오류가 표준 출력에서 ​​복사되기 때문입니다"라고 말해야 할 것 같습니다. STDOUT이 파일로 전달되기 전에 STDERR이 STDOUT으로 전송되면 파일에 STDOUT 및 STDERR이 포함되지 않습니까?

누구든지 이 문제를 해결하도록 도와줄 수 있나요? 내 독해력이 부족한 탓일까? 이 맥락에서 "반복"이라는 단어를 사용하는 것이 나에게는 약간 이상하게 보입니다. 어쩌면 이것이 나를 혼란스럽게 할 수도 있습니다.

답변1

복사여기서 정말 중요한 부분입니다.

리디렉션되기 전에 파일 설명자가 어디로 가는지 살펴보겠습니다. 이는 일반적으로 현재 터미널입니다. 예를 들면 다음과 같습니다.

STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1

이제 ls -l리디렉션 없이 호출하면 출력 및 오류 메시지가 내 터미널로 이동합니다 /dev/pts/1.

STDOUT먼저 파일( )로 리디렉션하면 ls -l > dirlist다음과 같습니다.

STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1

언제 우리가그 다음에리디렉션STDERR복사STDOUT( ls -l > dirlist 2>&1) 의 파일 설명자는 STDERR다음의 복사본으로 이동합니다 /home/bon/dirlist.

STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist

우리가 원한다면첫 번째리디렉션할 파일 설명자( ) 의 복사본 STDERR:STDOUTls -l 2>&1

STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1

그리고그 다음에 STDOUT파일( ls -l 2>&1 > dirlist)에 대해 다음을 얻습니다.

STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1

이 시점에서 STDERR우리는 여전히 터미널로 가야 합니다.

보시다시피 매뉴얼 페이지의 순서가 정확합니다.


테스트 리디렉션

이제 직접 테스트해 볼 수 있습니다. 를 사용하면 현재 프로세스가 어디로 가고 있는지 (fd 1 사용) 및 (fd 2 사용) ls -l /proc/$$/fd/확인할 수 있습니다 .STDOUTSTDERR

$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1

파일 설명자가 가리키는 위치를 표시하는 작은 셸 스크립트를 만들어 보겠습니다. 이렇게 하면 ls호출 셸의 리디렉션을 포함하여 항상 호출 시 상태를 얻을 수 있습니다 .

$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh

( 를 사용하면 CtrlD파일 끝 문자를 보내서 에서 cat읽기 명령을 중지할 수 있습니다 STDIN.)

이제 다양한 리디렉션 조합을 사용하여 이 스크립트를 호출하세요.

$ ./lookfd.sh 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh

STDOUT파일 설명자 1(의 경우 )과 2(의 경우 )가 서로 다른 것을 확인할 수 있습니다 STDERR. 재미로 리디렉션 STDIN하고 결과를 볼 수도 있습니다.

$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh

(독자에게 남은 질문: 파일 설명자 255는 어디를 가리키는가? ;-) )

답변2

아니요, 지침이 정확합니다.

처음에 1이 터미널을 가리키고 2도 터미널을 가리키는 경우:

command  2>&1   1>somewhere

리디렉션 평가는 왼쪽에서 오른쪽으로 진행됩니다.

따라서 먼저 평가 2>&1한 다음 1fd가 가리키는 내용(예: 파일 설명자 , 일반적으로 /dev/tty)을 the terminalfd에 복사합니다 2.

따라서 이때 fd는 이제 fd가 한때 ( ) 를 가리켰던 2위치를 가리킵니다 .1the terminal

그런 다음 해당 섹션을 평가하여 1>somewherefd의 파일 설명자가 복사됩니다(따라서 이 시점에서 fd는 이제 가리키고 fd는 여전히 가리킵니다).somewhere11somewhere2the terminal

따라서 1이 변경되기 전에 1에서 2가 복사되었으므로 1을 "어딘가"에 인쇄하고 2를 터미널에 인쇄합니다.

또 다른 순서:

command  1>somewhere 2>&1

먼저 fd 1를 로 리디렉션 somewhere한 다음 동일한 참조를 fd 2에 복사하므로 결국 2도 를 가리킵니다 somewhere. 그러나 이제부터 그들은 더 이상 "연락"하지 않습니다. 각각은 여전히 ​​개별적으로 리디렉션될 수 있습니다.

전임자:

command  1>somewhere 2>&1
exec 2>/dev/null

마지막에 fd는 1를 가리키고 somewherefd는 2다음을 향합니다./dev/null

fd의 일반 이름 1은 STDOUT(표준 출력)이고 fd의 일반 이름 2은 STDERR(표준 오류, 일반적으로 STDOUT을 방해하지 않고 오류를 표시하는 데 사용되므로)입니다.

답변3

여기서 혼란스러운 부분은 stderr를 stdout으로 리디렉션하면 실제로 두 스트림을 연결한다는 오해라고 생각합니다.

이것은 완전히 합리적인 생각이지만 2>&1stderr에 쓸 때 일어나는 일은 stdout이 무엇을 쓰고 있는지 살펴보고 동일한 위치 자체에 쓰는 것입니다. 따라서 이후에 stdout에 다른 곳에 쓰라고 지시하면 이동된 stderr의 대상에는 아무런 영향을 미치지 않습니다.

나는 이것이 약간 직관에 어긋난다고 생각하지만 이것이 작동하는 방식입니다. 글을 쓰고 싶은 위치를 설정한 다음 모든 사람에게 "나를 복사하세요"라고 말하세요. 그 내용이 명확해지기를 바랍니다...

답변4

복사...

중요하지만 더 중요한 것은많은 혼란의 근원. 정말 간단합니다. 이 답변은 단지 "급진적인" 예시일 뿐입니다.

허용되는 답변은 좋지만 너무 길고 "반복"을 강조합니다.

질문은 현명하게 다음과 같이 끝납니다.

이것반복이라는 단어의 사용이런 경우에는 좀 이상하다고 생각합니다. 어쩌면 이것이 나를 혼란스럽게 할 수도 있습니다.

나는 bash 표기법을 사용하고 파일이 "1"과 "2"를 처리하도록 "one"과 "two" 변수를 정의했습니다. (출력) 리디렉션 연산자 >는 할당입니다 =. &그리고 $"가치"를 의미합니다.

man bash 예(기본값 "1" 추가)

ls 1>dirlist 2>&1      # both to dirlist
ls 2>&1 1>dirlist      # 1 to dirlist, 2 stays on tty/screen 

다음과 같이 됩니다:

one=dirlist  two=$one

그리고

two=$one   one=dirlist

나나 다른 사람들에게는 이것이 자동으로 이루어지는 것이 아닙니다. 첫 번째 줄은 나가고 $one$two다 "dirlist"를 포함합니다. 틀림없이.

두 번째 줄은 쓸모없는 할당으로 시작됩니다. 두 정의 모두 "TTY"로 시작합니다(다소 상징적으로).방향;이 할당은 값을 변경하지 않으며 변수(예: 파일 핸들)의 경우 마술처럼 연결된 것이 없습니다. 변수는 two다음의 영향을 받지 않습니다 one=dirlist. 당연히 아니지.

누군가(6년 전) "복사" 또는 "복제"를 "가리키기"로 바꾸자고 제안한 후 깨달았습니다. 그것도 혼란스러울 것입니다.

그러한 복제나 포인터 의미론이 필요하지도 않습니다. 아마도 더 많은 주의가 필요한 것은 앰퍼샌드일 것입니다. 연산자/토큰/무엇이든의 "값"입니다.

놀라운 일자리 수를 얻을 수 있는 방법을 찾고 있는 경우에만편안, "완료" 메시지 및 보너스로 "2"라는 파일이 표시되면 다음을 수행할 수 있습니다.

ls 1>2& 2>/dev/null

"라고 자연스럽게 읽힌다.copy"/"duplicate" 1을 2로 설정한 다음 둘 다 null로 설정합니다.. 그러나 아이디어가 잘못되었고 구문이 잘못되었습니다. (그러나 구문 오류는 없으며 유효함)

올바른 계획 방법은 둘 중 하나를 null로 리디렉션한 다음 다른 하나를 동일한 위치로 리디렉션하는 것입니다.

ls 1>/dev/null 2>&1
# or 
ls 2>/dev/null 1>&2

(앞의 "1"은 생략 가능)

(알겠습니다. acc.A는 너무 길지는 않지만 목록이 너무 많습니다. 또는 시각화는 매우 좋지만 설명은 그리 좋지 않습니다.)

관련 정보