파일 로거를 사용할 때 stderr은 stdout 전에 플러시됩니다.

파일 로거를 사용할 때 stderr은 stdout 전에 플러시됩니다.

내 Python 코드:

import sys
print "i am a daemon"
print "i will be run using nohup"
sys.stderr.write("i am an error message inside nohup process\n")

코드를 실행하면 python a.py다음과 같이 표시됩니다.

i am a daemon
i will be run using nohup
i am an error message inside nohup process

코드를 실행하면 nohup python a.py > a.log 2>&1 < /dev/null &a.log가 표시됩니다.

i am an error message inside nohup process
i am a daemon
i will be run using nohup

stdout 로그를 사용할 때 stderr 로그가 플러시/기록되는 이유는 무엇입니까 nohup?

답변1

나는 그것이 중요하지 않다고 생각합니다 nohup. 이렇게 하면 동일한 동작이 발생합니다 python a.py > a.log 2>&1.

Python은 내부적으로 C 파일 stdio를 사용할 가능성이 높습니다. 이렇게 하면 stdout터미널에 있을 때 라인 버퍼링이 발생하고 stdout파일일 때 버퍼링이 발생합니다. stderr항상 버퍼링되지 않습니다.

stdout파일로 리디렉션하면 stdout버퍼링이 라인 버퍼링에서 버퍼링으로 전환되고 printed 문자열이 버퍼에 걸리고 프로그램(스트림)이 닫힐 때만 플러시됩니다. 스트림은 stderr버퍼링되지 않으므로 파일로 더 빠르게 전송됩니다.

stdbufadjustStandardBuffering을 사용하여 라인을 올바른 순서로 강제로 인쇄 할 수 있습니다 .

stdbuf -o0 python a.py  >a.log 2>&1

답변2

이는 대부분의 언어에서 출력 스트림의 일반적인 동작입니다.버퍼링됨즉, write메모리의 버퍼가 실제로 기록되고, 버퍼가 일괄적으로 스트림에 기록됩니다. 터미널에 쓸 때 표준 출력은 라인 버퍼링되지만(즉, 개행 문자가 인쇄될 때마다 실제 쓰기가 발생함) 일반 파일이나 파이프에 쓸 때 표준 출력은 완전히 버퍼링됩니다(데이터는 메모리에 기록될 때까지) 메모리 버퍼가 가득 찼습니다.) Stderr는 버퍼링되지 않거나 라인 버퍼링됩니다.

Python에서는 파일을 열 때 버퍼링 유형을 선택할 수 있지만 표준 스트림은 선택할 수 없습니다. 모든 스트림을 버퍼링 해제하려면 다음을 설정할 수 있습니다.PYTHONUNBUFFERED환경 변수는 표준 스트림이 버퍼링되지 않도록 강제합니다. 아니면 할 수 있습니다stdbuf또는 아래에서 프로그램을 실행하십시오.unbuffer.

그러나 표준 출력이 리디렉션될 때 프로그램이 올바른 순서로 출력을 내보내지 않으면 이는 수정해야 하는 프로그램의 결함입니다. 특히, stdout에 기록된 출력과 관련된 오류 메시지를 발행하려면 먼저 stdout을 플러시해야 합니다.

print some_data
if errro_condition():
    file.stdout.flush()
    sys.stderr.write('Bad stuff happened\n')

관련 정보