티에 배관 할 때 stdout의 강제 라인 버퍼링


117

일반적으로 stdout라인 버퍼링됩니다. 즉, printf인수가 개행으로 끝나는 한 해당 행이 즉시 인쇄 될 것으로 예상 할 수 있습니다. 파이프를 사용하여로 리디렉션 할 때 유지되지 않는 것 같습니다 tee.

a항상 종료되는 문자열을 \n.NET으로 출력 하는 C ++ 프로그램 이 stdout있습니다.

자체적으로 실행되면 ( ./a) 모든 것이 예상대로 올바른 시간에 올바르게 인쇄됩니다. 그러나 tee( ./a | tee output.txt)로 파이프하면 종료 될 때까지 아무것도 인쇄하지 않으므로 tee.

fflush(stdout)C ++ 프로그램에서 각 인쇄 작업 후에 추가하여 수정할 수 있다는 것을 알고 있습니다. 그러나 더 깨끗하고 쉬운 방법이 있습니까? 예를 들어 stdout파이프를 사용하는 경우에도 강제 로 라인 버퍼링 되는 명령이 있습니까?

답변:


67

패키지의 unbuffer일부를 시도하십시오 expect. 시스템에 이미있을 수 있습니다.

귀하의 경우 다음과 같이 사용합니다.

./a | unbuffer -p tee output.txt

( -punbuffer가 stdin에서 읽고 나머지 인수의 명령에 전달하는 파이프 라인 모드 용입니다.)


덕분에,이 내가 컴파일 할 수 있었더라도, 일을 expect자신과 같은 unbufferOS X에서 기본적으로 포함하지 않는 것
houbysoft

@houbysoft : 나는 그것이 당신을 위해 일했다 기쁘다. unbuffer작은 스크립트 일 뿐이므로 전체 패키지를 다시 컴파일 할 필요가 없습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

네, 아마,하지만 ./configure && make십초 걸렸다 그리고 난 그냥 이동 unbuffer/usr/local/bin:)
houbysoft

3
brew를 통해 Mac (10.8.5)에 설치했습니다. brew install expect --with-brewed-tk
Nils

2
FWIW, unbuffer는 다소 혼란 스럽기 때문에 관련 구조는 unbuffer {commands with pipes/tee}.
가짜 이름

128

당신은 시도 할 수 있습니다 stdbuf

$ stdbuf -o 0 ./a | tee output.txt

맨 페이지의 (큰) 부분 :

  -i, --input=MODE   adjust standard input stream buffering
  -o, --output=MODE  adjust standard output stream buffering
  -e, --error=MODE   adjust standard error stream buffering

If MODE is 'L' the corresponding stream will be line buffered.
This option is invalid with standard input.

If MODE is '0' the corresponding stream will be unbuffered.

Otherwise MODE is a number which may be followed by one of the following:
KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.
In this case the corresponding stream will be fully buffered with the buffer
size set to MODE bytes.

그러나 이것을 명심하십시오.

NOTE: If COMMAND adjusts the buffering of its standard streams ('tee' does
for e.g.) then that will override corresponding settings changed by 'stdbuf'.
Also some filters (like 'dd' and 'cat' etc.) dont use streams for I/O,
and are thus unaffected by 'stdbuf' settings.

당신은 실행하지 않는 stdbuftee당신은 그것을 실행하고, a이것이 당신에 영향을 미치지 않습니다 있도록의 버퍼링 설정하지 않는 한, a'에서의 스트림 a의 소스를 제공합니다.

또한, stdbuf입니다 하지 POSIX하지만, GNU-로 coreutils의 일부입니다.


3
감사합니다. 그러나 이것은 OS X에서 사용할 수없는 것 같습니다 (질문은 osx-lion 태그가 있습니다).
houbysoft

2
@houbysoft - 나는 확신 GNU 도구는 OS X에 설치할 수 있습니다입니다
jordanm

1
@jordanm : 아마도,하지만 종류의 전체 GNU 도구를 설치는 ... 이것에 대한 잔인한 것 같아
houbysoft

1
이 답변 stdbuf은 이미 사용중인 Centos Linux 배포판에서 사용할 수 있지만 그렇지 않기 때문에 찬성했습니다 unbuffer. 감사!
Huw Walters

6
파이썬 스크립트의 경우 stdbuf가 작동하지 않지만 -u파이썬 측에서 버퍼링을 비활성화 하는 데 사용할 수 있습니다 .python3 -u a.py | tee output.txt
Honza

27

명령을 사용하여 의사 터미널에서 명령을 실행할 수도 있습니다 script(파이프에 라인 버퍼 출력을 적용해야 함)!

script -q /dev/null ./a | tee output.txt     # Mac OS X, FreeBSD
script -c "./a" /dev/null | tee output.txt   # Linux

주의 script명령은, 랩 된 명령의 종료 상태를 다시 전파되지 않습니다.


3
script -t 1 /path/to/outputfile.txt ./a내 사용 사례에 잘 맞았습니다. 모든 출력을 라이브 스트리밍하는 outputfile.txt동시에 쉘의 표준 출력으로 인쇄합니다. 사용할 필요가 없었습니다tee
Peter Berg

26

stdio.h에서 setlinebuf를 사용할 수 있습니다.

setlinebuf(stdout);

버퍼링을 "라인 버퍼링"으로 변경해야합니다.

더 많은 유연성이 필요하면 setvbuf를 사용할 수 있습니다.


8
이 솔루션이 왜 그렇게 적은 찬성표를 가지고 있는지 궁금합니다. 이것은 발신자에게 부담을주지 않는 유일한 해결책입니다.
oxygene

1
이것은 표준 C (또는 POSIX)가 아닙니다. 을 사용 setvbuf(stdout, NULL, _IOLBF, 0)하는 것이 더 낫습니다 . 이는 정확히 동일합니다.
rvighne

이것은 printf () ing 인 C ++ 프로그램을 사용하여 OS X Catalina에서 내 문제를 해결했으며 티에 파이핑했지만 프로그램이 완료되었을 때만 출력을 볼 수있었습니다.
jbaxter

2

대신 C ++ 스트림 클래스를 사용하는 경우 every std::endl 암시 적 플러시입니다. C 스타일 인쇄를 사용하면 제안한 방법 ( fflush())이 유일한 방법 이라고 생각합니다 .


4
불행히도 이것은 사실이 아닙니다. std :: endl 또는 std :: flush를 사용하는 경우에도 c ++ std :: cout에서 동일한 동작을 관찰 할 수 있습니다. 버퍼링은 상단에서 발생하며 Linux에서 가장 쉬운 솔루션은 setlinebuf (stdout); 프로그램의 작성자 일 때 main ()의 첫 번째 줄로, 소스 코드를 변경할 수 없을 때 위의 다른 솔루션을 사용합니다.
oxygene

1
@oxygene 이것은 사실이 아닙니다. 나는 그것을 시도했고 endl은 티에 배관 할 때 버퍼를 플러시합니다 (printf와 달리). 코드 : #include <iostream> #include <unistd.h> int main(void) { std::cout << "1" << std::endl; sleep(1); std::cout << "2" << std::endl; }. 여기에 정의 된 ENDL 항상 버퍼를 플러시 : en.cppreference.com/w/cpp/io/manip/endl
커티스 Yallop
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.