파이프에서 표준 출력 버퍼링을 끄는 방법은 무엇입니까?

파이프에서 표준 출력 버퍼링을 끄는 방법은 무엇입니까?

두 가지 명령을 호출하는 스크립트가 있습니다.

long_running_command | print_progress

인쇄에 long_running_command진전이 있었지만 만족스럽지 않았습니다. 나는 그것을 더 좋게 만들곤 했습니다 print_progress(즉, 진행 상황을 한 줄에 인쇄합니다).

질문:stdout에 파이프를 연결하면 4K 버퍼도 활성화되므로 예쁜 인쇄 프로그램은 아무것도 얻지 못합니다... 아무것도... 아무것도...많이...:)

4K버퍼를 비활성화하려면 어떻게 해야 합니까 long_running_command? (아니요, 소스 코드가 없습니다.)

답변1

이 고양이의 가죽을 벗기는 또 다른 방법은 다음과 같습니다.stdbufGNU Coreutils의 일부인 프로그램입니다(FreeBSD에도 자체 프로그램이 있습니다).

stdbuf -i0 -o0 -e0 command

이렇게 하면 입력, 출력 및 오류 버퍼링이 완전히 꺼집니다. 일부 애플리케이션의 경우 성능상의 이유로 행 버퍼링이 더 적합할 수 있습니다.

stdbuf -oL -eL command

이는 동적으로 링크된 애플리케이션의 stdio버퍼링( printf(), fputs()...)에서만 작동하며 해당 애플리케이션 자체가 표준 스트림의 버퍼링을 조정하지 않는 경우에만 작동합니다. 단, 이는 대부분의 애플리케이션에 적용되어야 합니다.

답변2

당신은 그것을 사용할 수 있습니다unbuffer명령(다음과 같이expect패키지), 예를 들어

unbuffer long_running_command | print_progress

unbuffer의사 터미널(pty)을 통해 연결하면 long_running_command시스템이 이를 대화형 프로세스로 처리하므로 파이프에서 4kiB 버퍼를 사용하지 않아 대기 시간이 발생할 수 있습니다.

더 긴 파이프의 경우 모든 명령(마지막 명령 제외)을 버퍼링 해제해야 할 수도 있습니다.

unbuffer x | unbuffer -p y | z

답변3

의 경우 grep출력 을 라인 버퍼링하도록 강제할 수 있습니다 sed. awk당신은 그것을 사용할 수 있습니다 :

grep --line-buffered

출력을 라인 버퍼링하도록 강제합니다. 기본적으로 출력은 표준 출력이 터미널인 경우 라인 버퍼링되고, 그렇지 않은 경우 블록 버퍼링됩니다.

sed -u

출력 라인을 버퍼링하도록 만듭니다.

자세한 내용은 이 페이지를 참조하세요. http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html

답변4

출력이 터미널에 도달하지 않을 때 libc가 버퍼링/플러싱을 수정하는 데 문제가 있는 경우 다음을 시도해야 합니다.소캇. 거의 모든 유형의 I/O 메커니즘 간에 양방향 스트림을 생성할 수 있습니다. 그 중 하나는 의사 tty와 통신하는 포크된 프로그램입니다.

 socat EXEC:long_running_command,pty,ctty STDIO 

그 기능은

  • 의사 tty 생성
  • long_running_command를 포크하고 pty의 슬레이브 쪽을 stdin/stdout으로 설정합니다.
  • pty의 기본 측면과 두 번째 주소(여기서는 STDIO) 사이에 양방향 스트림을 설정합니다.

이것이 동일한 출력을 제공한다면 long_running_command파이프를 계속 사용할 수 있습니다.

편집: 와우, 버퍼링되지 않은 답변을 보지 못했습니다! 음, 어쨌든 socat은 훌륭한 도구이므로 아마도 이 답변을 남길 것입니다.

관련 정보