Bash에서 다음 동작을 관찰합니다.
{ echo 'foo' ; sleep 10 ; }
-> stdout "foo"가 즉시 나타나고 명령은 10초 후에 완료됩니다(예상대로).
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo')
-> stdout "foo"가 즉시 나타나고 명령은 10초 후에 완료됩니다(예상대로).
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo' | grep 'oo')
-> 10초 후에 stdout "foo"가 나타납니다.
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo' >&2)
-> 10초 후 stderr "foo"
명령 대체에서 단일 grep을 사용하는 명령줄은 결과를 즉시 출력하는 반면 파이프와 리디렉션이 있는 변형은 절전 모드가 끝날 때까지 기다리는 이유는 무엇입니까?
답변1
그렇게 공상할 필요는 없습니다. 동일한 효과를 관찰할 수 있습니다.
{ echo 'foo' ; sleep 10 ; } | grep oo | grep oo
또는
{ echo 'foo' ; sleep 10 ; } | grep oo | cat
또는
- 두 개의 터미널을 엽니다. 두 디렉토리 모두에서 동일한 디렉토리(예: 홈 디렉토리 또는
/tmp
)로 이동합니다. - 그 중 하나에서 을 수행하십시오
{ echo 'foo' ; sleep 10 ; } | grep oo > foo.out
. - 반면에
ls -ld foo.out
반복적으로 수행하십시오. 파일이 즉시 나타나지만 10초 동안 크기가 0이었다가 이후 4바이트 길이가 되는
것을 볼 수 있습니다 .foo.out
간단히 말해서, grep
(표준) 출력이 터미널인지 테스트하십시오. 그렇다면 작성된 것만큼 빠르게 출력을 작성합니다. 그렇지 않은 경우 출력을 버퍼링하고 씁니다.질소 1바이트, 여기서질소 일반적으로 512이지만 일부 구현에서는 다를 수 있습니다.
답변2
Scott의 답변을 확장하면 다음과 같습니다.
비교하다
{ echo 'foo' ; sleep 3 ; } | grep oo | cat
그리고
{ echo 'foo' ; sleep 3 ; } | stdbuf -o 0 grep oo | cat