진행률 보고서 / 로깅 정보가 stderr 또는 stdout에 속해 있습니까?


75

진행 보고서 및 로깅 정보 ( "Doing foo; foo done"등)를 인쇄해야하는 공식 POSIX, GNU 또는 기타 지침이 있습니까? 개인적으로, 나는 stdout을 리디렉션하고 프로그램의 실제 출력 만 가져올 수 있도록 stderr에 작성하는 경향이 있습니다. 최근에 진행 보고서가 실제로 오류가 아니며 오류 메시지 만 stderr에 인쇄해야하기 때문에 이것이 좋은 습관이 아니라고 들었습니다.

두 위치 모두 의미가 있으며, 물론 당신이하는 일의 세부 사항에 따라 하나 또는 다른 것을 선택할 수 있지만, 일반적으로 인정되는 표준이 있는지 알고 싶습니다. POSIX, GNU 코딩 표준 또는 기타 널리 인정되는 모범 사례 목록에서 특정 규칙을 찾을 수 없었습니다.

비슷한 질문이 있지만이 정확한 문제를 해결하지 못합니다.

따라서 진행률 보고서 및 기타 정보 메시지 (프로그램의 실제 출력에 포함되지 않은)를 인쇄해야하는 공식적인 규칙이 있습니까?


26
stdout결과와 함께 스피너 등을 인쇄 하면 결과를 쓸모 없게 만드는 안전한 방법입니다. 결과를 다른 프로그램으로 파이프해야하는 경우, 해당 프로그램은 결과를 스피너와 분리해야합니다. 또한 출력을 파일로 리디렉션하면 회전자가 표시되지 않습니다. 이모.
Satō Katsura

2
@SatoKatsura 네, 저의 의견이기도합니다. 그래서 stderr에 인쇄합니다. 그러나 내가 일하는 회사의 CTO는 stderr로 인쇄하는 것이 문제가 있음을 나타냅니다. 나는 POSIX Way®가 stderr에 인쇄하고 있다는 것을 과감하게 주장했다. 그가 저에게 20 년의 이상한 경험을 가지고 있다는 것을 감안할 때, 저는 일종의 "공식적인"지침을 찾을 수 있는지 알고 싶습니다.
terdon

사토 카츠라 (Sato Katsura)가 말한 stdout것처럼 스피너와 다른 유익한 메시지를 가지 치기위한 안전하고 올바른 방법이지만 많은 프로그래머들이 말하는 것처럼 '침묵은 황금이다. 모든 것이 괜찮다면 아무것도 출력하지 않습니다. ' 그래서 사실, 표준 오류는 항상 sequence.for 파이프 깨질 수도 STDOUT 것을 때문에 모호한 정의 할하는 데 사용되는 공식 가이드
벤 괜찮다을

6
@Seven 나는 당신이 오해 한 것 같아; Sato는 stdout을 사용하는 것이 안전하지 않다고 말합니다 ( "결과를 쓸모 없게 만드는 안전한 방법").
Stephen Kitt

1
하나의 가능한 모든 크기의 솔루션은 플래그가 사용될 stderr때를 제외하고 --verbose진행률 보고서도 포함되는 경우를 제외하고 오류 메시지 만보 고하는 것입니다.
Gaurav

답변:


27

Posix는 표준 스트림 다음과 같이 정의합니다 .

프로그램 시작시 표준 입력 (일반 입력 읽기), 표준 출력 (일반 출력 쓰기) 및 표준 오류 (진단 출력 쓰기 )의 세 가지 스트림을 미리 정의해야하며 명시 적으로 열 필요는 없습니다 . 열면 표준 오류 스트림이 완전히 버퍼링되지 않습니다. 표준 입력 및 표준 출력 스트림은 스트림이 대화식 장치를 참조하지 않는 것으로 결정될 수있는 경우에만 완전히 버퍼링됩니다.

GNU C 라이브러리 유사 표준 스트림을 설명합니다 :

변수 : FILE * stdout
표준 출력 스트림으로 프로그램의 일반 출력에 사용됩니다.

변수 : FILE * stderr
표준 오류 스트림으로, 프로그램이 발행 한 오류 메시지 및 진단에 사용됩니다.

따라서 표준 정의에는 "기존 / 정상 출력"및 "진단 / 오류 출력"이외의 스트림 사용에 대한 지침이 거의 없습니다. 실제로 진행률 표시기가 문제가되는 이러한 스트림 중 하나 또는 둘 모두를 파일 및 파이프 라인으로 리디렉션하는 것이 일반적입니다. . 일부 시스템 은 출력을 모니터링 stderr 하고 문제의 징후로 간주합니다. 따라서 보조 보조 진행 정보는 어느 스트림에서나 문제가됩니다.

대신 무조건으로 진행 표시기를 보내는 표준 스트림, 그 진행 출력에만 적합 인식하는 것이 중요 상호 작용 스트림. 이를 염두에두고 스트림이 대화 형인지 (예 :로 isatty()) 또는 명령 줄 옵션으로 명시 적으로 활성화 된 경우 에만 진행 카운터를 작성하는 것이 좋습니다 . % 완료 바와 같이 이해하기 위해 터미널 업데이트 동작에 의존하는 진행 미터에 특히 중요합니다.

매우 간단한 진행 메시지 ( "Starting X"... "Done with X")의 경우 비 대화식 스트림에 대해서도 출력을 포함하는 것이 더 합리적입니다. 이 경우로 검색 grep또는 페이징 less또는 모니터링과 같이 사용자가 스트림과 상호 작용하는 방법을 고려하십시오 tail -f. 이러한 상황에서 진행 메시지를 보는 것이 합리적이라면에서보다 쉽게 ​​사용할 수 있습니다 stdout.


고마워, GNU 지침은 내가 추구하는 일종의 것입니다. 그러나 나는 내 질문이 약간 오도되었다는 것을 알고 있습니다. "진보 보고서"에 대해 언급했을 때, 나는 좋아하는 것과 같은 N% done것을 생각 doing foo하고 foo done있었습니다. 후자는 파일로 리디렉션 될 때 디버깅에 사용되므로 항상 보관해야합니다. 따라서 스트림이 대화 형인지 여부를 확인하라는 제안은 적용 할 수 없습니다 (일반적으로 매우 좋은 생각 임).
terdon의

아 감사는 명확한 설명, 그건 당신이 같은 소프트웨어에서 볼 "% 완료"와 해시 마크 진행률 표시 줄과 같은 단지 물건에서 조금 다르다 curlyum. 이 경우, 나는 사용자가를 통해 출력과 상호 작용 할 것인지 여부와 방법에 대해 생각 grep하거나 less유사한 도구 나.
Bradd Szonye

위의 설명을 포함하도록 답변이 업데이트되었습니다.
Bradd Szonye

71

POSIX 는 표준 오류를 다음과 같이 정의합니다

진단 출력용

오류 메시지로만 사용되는 것은 아닙니다. 진행 정보를 진단 출력으로 간주하므로 표준 오류에 속합니다.


8
파이썬에서 FWIW stdout는 기본적으로 라인 버퍼링되는 반면 stderr버퍼링되지 않으므로 stderr줄 바꿈이 포함되지 않은 진행률 텍스트 / 막대 / 스피너를 작성하는 자연스러운 선택입니다. (이러한 텍스트를 작성하는 경우 stdout진행률 출력 호출을 복잡 stdout.flush()하게 표시하여 표시해야합니다.)
PM 2Ring

12
POSPMIX는 파이썬에만 국한된 것이 아니라 스트림을 그런 식으로 정의합니다.
Stephen Kitt

4
@ PM2Ring :에 쓸 때 리디렉션 될 때 진행률 보고서가 실제로 실시간으로 표시되도록하려면 stdout텍스트 에 줄 바꿈 포함되어 있어도 비워야 합니다.

@Hurkyl Ah, 좋은 지적입니다. 리디렉션을 고려하지 않았습니다.
PM 2Ring

1
@ 워터? 종료 상태가 0이면 Ansible이 stderr 텍스트를 삼킨다. 그 주장은 단순히 거짓이다.
Charles Duffy

10

POSIX는 Shell and Utilities , 1.4의 "진단 정보"에 대해 약간 더 구체적입니다 . 유틸리티 설명 기본값 (강조 광산) :

STDERR

STDERR 섹션은 유틸리티의 표준 오류 출력을 설명합니다. 유틸리티가 의도적으로 보낸 메시지 만 설명합니다. 표준 오류에 터미널을 사용하면 표준 오류 출력을 기록하는 표준 유틸리티가 백그라운드에서 사용될 때 중지 될 수 있습니다. 이러한 이유로 응용 프로그램은 백그라운드에서 스크립트에 대화 형 기능을 사용해서는 안됩니다.

대부분의 유틸리티에 대한 진단 메시지 형식은 지정되어 있지 않지만이 POSIX.1-2008 볼륨으로 형식이 지정되지 않은 진단 및 정보 메시지의 언어 및 문화적 규칙은 LC_MESSAGES 및 [XSI] [옵션 시작] 설정의 영향을받습니다. ] NLSPATH. [옵션 끝]

표준 유틸리티의 지정된 표준 오류 출력은이 POSIX.1-2008 볼륨에서 제공하는 것을 제외하고이 POSIX.1-2008 볼륨에 정의 된 환경 변수의 존재 또는 값에 의존하지 않아야합니다.

기본 동작 :이 섹션이 "표준 오류는 진단 메시지에만 사용해야합니다."로 표시되면 달리 명시하지 않는 한 종료 상태에 오류가 있음을 나타내는 경우에만 진단 메시지가 표준 오류로 전송 됨을 의미합니다. 이 POSIX.1-2008 볼륨에서 설명한대로 유틸리티가 사용되었습니다.

이 섹션이 "사용되지 않음"으로 표시되면 POSIX.1-2008의이 볼륨에 설명 된대로 유틸리티를 사용할 때 표준 오류를 사용하지 않아야합니다.

IANASL,하지만 유틸리티가 오류 종료 코드를 반환하는 경우에만 stderr이 출력을 의미한다는 것을 해석합니다. 성공적인 실행을위한 정상적인 이벤트 과정이 아니므로 오류가 발생 하지 않는 한 (물론, 달리 지정되지 않은 경우) POSIX 유틸리티가 진행 정보를 인쇄하지 않아야합니다 .


표준 오류 사용에 대한 일반적인 정의가 아니라 각 POSIX 유틸리티의 사양에 제공된 "STDERR"섹션의 의미를 설명하는 것으로 이해합니다. terdon이 표준 POSIX 유틸리티를 작성하고 있다고 생각하지 않습니다. ;-).
Stephen Kitt

1
@StephenKitt도 나도 마찬가지입니다. 그러나 그는 CTO와 논쟁 중입니다. CTO는 stderr 출력이 잘못되었다는 표시이며 표준은 기본 행동으로서의 주장을 뒷받침합니다.
muru December

1
POSIX 유틸리티 의 기본 동작으로 만 클레임을 지원하며 특정 경우 (언급 된 문구를 사용하는 유틸리티)에서만 클레임을 지원합니다 . POSIX의이 부분은 규범 (AIUI)이 아니며 템플릿입니다. 유틸리티 사양을 읽는 방법을 알려주며 유틸리티의 동작을 지정하지 않습니다. 특히 "표준 오류는 진단 메시지에만 사용됩니다"라는 문구의 의미를 정의합니다. "사용되지 않습니다." 유틸리티 사양의 "STDERR"섹션에 있습니다. 각 유틸리티는 해당 동작을 지정하며 해당 문구를 속기로 사용할 수 있습니다.
Stephen Kitt

내 요점을 바꾸지 않는 @StephenKitt. POSIX 유틸리티는 a) stderr로 출력하지 않습니다. b) 문제가 발생한 경우 진단 메시지에만 사용합니다. c) 문제가없는 경우 진단 메시지에만 사용합니다. d) 다른 용도로 사용합니다. 달리 명시하지 않는 한 (a, b) 문제가있는 경우 진단 메시지에만 사용한다고 말했다 (c, d). 이제 내 주장은 이것이 기본값이라는 것입니다. 그것이 템플릿이기 때문입니다.
muru December

2
POSIX 유틸리티는 표준 오류에 대한 진행 정보를 출력하도록 표준을 지정할 수 있다는 점을 잘 설명 할 수 있습니다. 종료 코드에도 오류가있는 경우 "기본 동작"(관련 섹션에서 여전히 언급해야 함)이 표준 오류 만 사용하는 것이 흥미 롭습니다. 그러나 그것은 제한적이지 않습니다.
Stephen Kitt

7

제외 원칙에 따르면 stderr로만 갈 수 있습니다. 그렇습니다. 스티븐 키트가 제공 한 POSIX 사양에 대한 링크를 넘어서서 stderr이 진단 목적임을 나타내는 공식 사양에 대해 질문 한 것을 알고 있습니다.

더 중요한 점은 stdin과 stdout이 진행 보고서를 stdout으로 인쇄하는 것을 허용하지 않는 기능을 가지고 있다는 것입니다. 물론 Unix 쉘 명령에서 부작용이 아니라 강력한 파이프 라이닝 방식의 핵심 인 파이프 시퀀스를 형성합니다. .

그래서. 프로그램의 실제 "페이로드"를 제외하고는 stdout에 속하지 않습니다. 프로그램에 출력이 없으면 stdout으로 이동하지 않아야합니다. 이것은 진행 보고서를 포함하여 다른 모든 것에 대한 stderr을 남깁니다 .

물론, 이것은 구멍을 남깁니다. 아마도 "stdfluff"또는 출력이나 오류가 아닌 진행률 보고서, 디버깅 및 그와 비슷한 것을 갖는 것이 좋을 것입니다. 사실, 아무것도하지 않아도됩니다. 즉, 진행 상황을 파일 디스크립터 3에 인쇄 할 수 있습니다. 예 :

$ perl -e 'open($fd, ">", "/dev/fd/3"); print $fd "hello\n"'

출력이 없습니다. (*)

$ perl -e 'open($fd, ">", "/dev/fd/3"); print $fd "hello\n"'  3>&1
hello

이것은 fd-3으로 인쇄되고 stdout으로 리디렉션됩니다.

(*) 첫 번째 예제는 출력을 생성하지 않지만 여전히 약간 가져옵니다. 는 open실패하고 $!포함됩니다 no such file or directory; 예를 들어 이것을 예로 들면, 본격적으로 이와 같이 사용되는 것은 아닙니다. 실제 프로그램에서이 경로를 사용하려면 /dev/fd/3사용 가능 여부를 테스트 하고 진행률 보고서를 활성화할지 여부에 대한 힌트로 사용할 수 있습니다. 당신 open은 실제 파일과 같은 것들에 대해 자신 의 혼란에 빠지지 않도록 꽤 일찍해야 할 것입니다 ...


무엇입니까 fd-3? 세 번째 플로피 디스크?
Peter Mortensen

파일 설명자 3, @PeterMortensen
AnoE

-1

사용 메시지는 사용자가 호출 한 경우 stdout --help으로, 실수 한 경우 stderr 로 이동해야합니다 . 무조건 stderr에 인쇄하는 것은 호출기 / grep 등으로보기가 더 어려워지기 때문에 불쾌합니다.

또한 세 번째 방법을 제안 할 수 있습니다. 진행률 보고서 / 스피너 등을 위해 / dev / tty를여십시오.


6
죄송하지만 질문에 대답하지 않습니다. 나는 의견이 아닌 공식 지침을 구체적으로 요구 했다. 어쨌든 내가 의견을 물었더라도 다른 질문에 대답하고 있습니다. 나는 --help메시지에 대해 전혀 말 하거나 도움이 되지 않습니다 . 질문을 다시 읽으십시오.
terdon

당신은 "사용 메시지"를 언급했는데, 나는 그것이 당신이 연결 한 다른 질문의 제목이 아니라 당신의 질문의 일부라고 생각했습니다. 왜 "공식 지침"이 존재한다고 생각하는지 모르겠습니다. 누가 그들을 만들 권한이 있습니까?
Random832

3
나는 그들이하는 것을 모른다. 그래서 나는 묻는다. 그리고 공식적으로 POSIX 표준에는 프로그램 작동 방식에 대한 다양한 세부 사항에 대한 사양이 있습니다. 스티븐이 자신의 답변에서 지적한 것처럼 stderr로 가야 할 것에 대한 모호한 제안. GNU 코딩 표준도 비슷한 것을 가질 수 있습니다. 기본적으로, * nix 생태계를 위해 활동하고 코드를 생성하는 모든 그룹은 내가 관심있는 표준을 가질 수 있습니다.
terdon

@terdon 기존 프로그램이 무엇을하는지 예를 들어 보시겠습니까? curl, wget 및 pv는 모두 stderr을 사용합니다. wget 및 pv는 tty가 조건부로 만들고 curl은 stdout이 tty가 아닌 조건부로 만듭니다.
Random832

4
또한, 같은 소리 당신의 CTO가 호출 프로그램에 오류가 발생했음을 의미가 아닌 종료 상태보고로 표준 오류 데이터의 존재에 반응해야한다고 생각한다. 이것은 분명히 나쁜 습관이며 (종료 상태를 확인하는 것보다 쓰기가 어렵습니다) 그를 설득하기에 더 좋은 각도 일 수 있습니다.
Random832
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.