명령은 { echo err >&2; echo out >&1; } | :
"err"을 인쇄할 수 있는데 두 번째 명령은 인쇄할 수 없는 이유는 무엇입니까?
컨테이너의 일부 테스트:
- 더반:11.5(배쉬/5.1.4)
- 로키리눅스:9.0(배쉬/5.1.8),
- 중앙 운영 체제: 1908년 7월 7일(bash/4.2.46),
- CentOS: 8.4.2105(bash/4.4.19).
이는 호스트 CentOS 8.0.1905, Debian 11.4에서도 발생합니다.
~# { echo err >&2; echo out >&1; } | :
err
~# { echo out >&1; echo err >&2; } | :
~#
다음을 사용하지 않는 :
것이 올바른 것 같습니다 .
~# { echo out >&1; echo err >&2; } | sed 's/.*/-&-/'
err
-out-
~#
그러나 다른 호스트 CentOS 7.7.1908(bash/4.2.46)에서는 다음과 같이 인쇄됩니다.
~# { echo out >&1; echo err >&2; } | :
err
~#
답변1
사이의 차이
{ echo err >&2; echo out >&1; } | :
... 그리고
{ echo out >&1; echo err >&2; } | :
echo
...두 호출이 이루어진 순서입니다. 순서는 진행 방법에 따라 중요합니다.빠르게첫 번째 echo
실행이 가능합니다.
파이프의 양쪽은 동시에 시작되며 { ...; }
표준 입력 스트림에서 읽지 않습니다. 이는 파이프라인이 종료되자마자 거의 즉시 제거된다는 것을 의미합니다.:
:
:
echo out >&1
파이프가 해체되면 쓸 파이프 버퍼가 없습니다 . 존재하지 않는 파이프에 쓰려고 하면 echo
파이프의 왼쪽이 PIPE 신호를 받아 죽습니다.
실행 전에 종료 되면 echo err >&2
출력이 없습니다.
그래서:
파이프 상태는 고려되지 않으므로 항상
err
출력을 얻게 됩니다 .{ echo err >&2; echo out >&1; } | :
echo err >&2
err
때로는 다음과 같은 결과가 출력됩니다.{ echo out >&1; echo err >&2; } | :
~에 따르면:
이전에 종료된 경우에도echo out >&1
실행할 수 있는 기회가 있습니다. 먼저 종료 되면:
왼쪽이 조기에 종료되므로 출력이 없습니다.
내 생각에는 대부분의 사람들이 대부분의 시스템에서 두 번째 파이프의 비결정적 동작을 경험하지 않을 것입니다. 그럼에도 불구하고 이를 보여주는 운영 체제와 셸 버전의 조합을 찾을 수 있습니다. 또한 단일 쉘 세션 내에서도 FreeBSD의 비결정적 동작을 복제했습니다 zsh
(비록 쉘이 다른 동작보다 한 동작을 선호하는 것처럼 보였지만 마침내 전환을 확인하기까지 10번 더 시도해야 했습니다).
답변2
(우선, 무언가를 시도하고 있는데 그것이 어떻게 작동하고 무엇을 하는지 확신할 수 없다면 로그인한 상태에서 해당 작업을 중단하는 것이 좋습니다 root
.)
{ echo err >&2; echo out >&1; } | :
이는 문자열을 에코하고 err\n
해당 문자열을 포함하는 표준 출력은 표준 오류(터미널에 표시됨)로 리디렉션된 다음 문자열은 out\n
표준 출력으로 에코되어 표준 출력으로 리디렉션됩니다. 그런 다음 표준 출력이 다음으로 파이프됩니다. 표준 입력으로는 :
아무것도 출력하지 않습니다.
추가 테스트:
$ { echo err >&2; echo out >&1; } 1> outputfile 2> errorfile
$ for file in *; do echo $file; cat $file; done
errorfile
err
outputfile
out
$ rm errorfile outputfile
$ { echo err >&2; echo out >&1; } 1> outputfile 2> errorfile
$ for file in *; do echo $file; cat $file; done
errorfile
err
outputfile
out
그렇긴 하지만 어떤 경우에는 표준 오류로 인해 출력이 손실되는 것처럼 보이는 이유가 무엇인지 잘 모르겠습니다. 나는 이것을 재현할 수 없습니다:
$ { echo err >&2; echo out >&1; } | :
err
$ { echo out >&1; echo err >&2; } | :
err