간단한 설명

간단한 설명

이 최소한의 예를 고려하면

( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; )

출력하고 LINE 11초 후에 LINE 2,예상대로.


파이프로 연결하면grep LINE

( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE

동작은 이전 경우와 동일합니다.예상대로.


아니면 파이프로 연결하면cat

( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | cat

행동은 또 똑같고,예상대로.


하지만, 로 파이프 grep LINE한 다음 으로 파이프하면 cat,

( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE | cat

1초가 지날 때까지 출력이 없으며 두 줄 모두 출력에 즉시 나타납니다.나는 기대가 없다.


왜 이런 일이 발생합니까? 마지막 버전이 처음 세 명령과 동일하게 작동하도록 하려면 어떻게 해야 합니까?

답변1

(적어도 GNU) grep의 출력이 터미널이 아닌 경우 출력을 버퍼링하는데, 이것이 바로 여러분이 보고 있는 동작의 원인입니다. grepGNU 옵션을 사용하여 이 기능을 비활성화 할 수 있습니다 --line-buffered:

( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep --line-buffered LINE | cat

또는 stdbuf유틸리티:

( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | stdbuf -oL grep LINE | cat

파이프라인에서 버퍼링 끄기이 주제에 대해서는 더 많은 내용이 있습니다.

답변2

간단한 설명

많은 유틸리티와 마찬가지로 이는 특정 프로그램에 특정한 것이 아닙니다 grep.라인 버퍼그리고완전히 버퍼링됨. 전자의 경우 C 라이브러리는 이 데이터를 보유하는 버퍼가 채워지거나 개행 문자가 추가될 때까지(또는 프로그램이 완전히 종료될 때까지) 출력 데이터를 메모리에 버퍼링한 다음 write()실제로 버퍼 내용을 쓰기 위해 호출됩니다 . 후자의 경우, 메모리 버퍼가 꽉 찼을 경우(또는 프로그램이 깔끔하게 종료될 경우)에만 실행됩니다 write().

자세한 설명

이것은 잘 알려져 있지만 약간 잘못된 해석이다. 실제로 표준 출력은 라인 버퍼링되지 않습니다.스마트 버퍼링GNU C 라이브러리와 BSD C 라이브러리에 있습니다. 표준 출력은반품표준을 읽을 때 얼굴이 붉어짐입력하다배기가스그것은메모리 버퍼(입력보다 먼저 읽기) 및 C 라이브러리는 read()더 많은 입력을 얻기 위해 호출해야 함그리고새로운 줄의 시작 부분을 읽는 중입니다. (이에 대한 한 가지 이유는 다른 프로그램이 필터의 양쪽 끝에 연결되어 필터에 쓰는 것과 필터에서 읽는 것을 번갈아 가며 한 줄씩 작동할 수 있기를 원할 때 발생하는 교착 상태를 방지하기 위한 것입니다. GNU와 같습니다. ) 의 "코프로세스" awk.

C 라이브러리 영향

grep다른 유틸리티는 감지한 표준 출력, 더 엄밀히 말하면 이를 수행하는 데 사용하는 C 라이브러리를 기반으로 이 작업을 수행합니다. 이것이 C 프로그래밍의 정의 기능이기 때문입니다. 대화형 장치가 아닌 경우에는 전체 버퍼링을 선택하고, 그렇지 않은 경우에는 스마트 버퍼링을 선택합니다. 파이프는 대화형 장치로 간주되지 않습니다. 왜냐하면 적어도 Unix 및 Linux 세계에서는 대화형 장치의 정의가 기본적으로 isatty()관련 파일 설명자에서 true를 반환하는 호출이기 때문입니다.

전체 버퍼링을 비활성화하는 해결 방법

일부 유틸리티에는 이 결정을 변경하는 옵션 grep과 같은 특수 옵션이 있는데 --line-buffered, 보시다시피 이름이 잘못되었습니다. 그러나 실제로 사용할 수 있는 필터링 프로그램 중 이러한 옵션을 제공하는 프로그램은 거의 없습니다.

보다 일반적으로 C 라이브러리의 특정 내부를 파헤쳐 결정을 변경하는 도구를 사용하는 것이 가능합니다. 변경하려는 프로그램이 set-UID이고 특정 C 라이브러리에만 해당되는 경우 보안 문제가 있습니다. , 그리고 이는) C로 작성되거나 C 위에 계층화된 프로그램 또는 유사한 ptybandage도구 에만 해당됩니다.원하지 않는다프로그램의 내부 구조를 변경하되 단순히 의사 터미널을 표준 출력으로 삽입하여 결정이 "대화형" 형식으로 나타나도록 함으로써 이에 영향을 줍니다.

추가 읽기

답변3

사용

grep --line-buffered

grep이 한 번에 두 줄 이상을 버퍼링하지 않도록 합니다.

관련 정보