프로그램이 시작되면 시스템의 어느 부분이 세 가지 표준 스트림에 대한 버퍼링을 설정합니까?
이것은 Linux, glibc 또는 bash의 일부입니까? POSIX는 동작을 정의합니까, 아니면 C의 일부입니까?
Posix에는 몇 가지 답변이 있습니다.
https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05
프로그램 시작 시 표준 입력(일반 입력 읽기용), 표준 출력(일반 출력 쓰기용) 및 표준 오류(진단 출력 쓰기용)의 세 가지 스트림이 미리 정의되어 있으므로 명시적으로 열 필요가 없습니다. 열릴 때 표준 오류 스트림은 완전히 버퍼링되지 않습니다. 표준 입력 및 표준 출력 스트림은 표준 입력 및 표준 출력 스트림이 대화형 장치를 참조하지 않는다고 판단할 수 있는 경우에만 완전히 버퍼링됩니다.
따라서 시스템이 스트림이 대화형이 아니라고 판단할 수 있다면 완전히 버퍼링될 수 있습니다(stderr 제외). 그러나 실제로 이것이 시스템의 어느 부분을 결정합니까?
답변1
당신의 프로그래밍 언어
이 동작은 C 런타임 라이브러리의 아티팩트이자 C 프로그래밍 언어의 요구 사항입니다. 다른 프로그래밍 언어는 역사적으로 C 런타임 라이브러리 위에 구축되어 이 동작을 C 런타임 라이브러리에서 파생했습니다. 예를 들어 C++ 프로그램의 경우에도 마찬가지입니다. C 및 C++ 언어 표준의 장은 스택 오버플로(qv)에서 자주 인용됩니다.
특히 Python으로 작성된 프로그램은 동일한 동작을 가지며 종종 의문을 제기하며 때로는 프로그래밍 언어의 런타임 동작이 크게 잘못되었다는 비난을 받습니다.
프로그램을 수정하고 다시 컴파일하지 않고 기본 언어 의미를 사용하여 프로그램의 이러한 동작을 변경하는 도구는 두 가지 형태로 제공됩니다. 즉, 런타임에 자신을 삽입하고 버퍼링을 변경하는 언어 종속(때때로 런타임 라이브러리 특정) 도구와 변환 도구입니다. 런타임 라이브러리가 대화형 장치라고 판단하는 파일에 대한 표준 I/O입니다. 후자 범주의 도구는 Bernstein을 포함하여 언어에 구애받지 않습니다 ptybandage
.
추가 읽기
- https://unix.stackexchange.com/a/407472/5132
- https://unix.stackexchange.com/a/249801/5132
- http://git.musl-libc.org/cgit/musl/tree/src/stdio/__stdout_write.c#n8
버퍼링 문제의 몇 가지 예:
- 즉시 Python stdout을 파일에 쓰기
- 내 서비스에서 시스템 서비스 로그를 더 빠르게 가져오기
- Systemd Python 서비스가 모든 출력을 syslog로 보내지 않음
- 하나의 단위로 실행되는 Python 스크립트의 출력은 순서가 없지만 셸은 영향을 받지 않는 것처럼 보입니다.
- Daemontools 멀티로그는 로그 줄 시간 정보를 잃습니다. 어떻게 고치나요?
- 파일 로거를 사용할 때 stderr은 stdout 전에 플러시됩니다.
- 하나의 단위로 실행되는 Python 스크립트의 출력은 순서가 없지만 셸은 영향을 받지 않는 것처럼 보입니다.
- systemd: fork()를 사용하는 프로세스는 하위 프로세스가 종료된 후에만 로그를 표시합니다.