진행 보고서와 로그 메시지(예: "Doing foo; foo done")를 인쇄해야 하는 공식 POSIX, GNU 또는 기타 지침이 있습니까? 개인적으로 나는 stdout을 리디렉션하고 프로그램의 실제 출력을 얻을 수 있도록 stderr에 작성하는 경향이 있습니다. 최근 누군가가 나에게 진행 보고서는 실제로 오류가 아니기 때문에 이것이 좋은 습관이 아니며 오류 메시지만 stderr에 인쇄되어야 한다고 말했습니다.
두 입장 모두 의미가 있으며, 물론 수행 중인 작업의 세부 사항에 따라 둘 중 하나를 선택할 수 있지만 이에 대해 보편적으로 인정되는 표준이 있는지 궁금합니다. POSIX, GNU 코딩 표준 또는 기타 널리 인정되는 모범 사례 목록에서 특정 규칙을 찾을 수 없습니다.
비슷한 질문이 몇 가지 있지만 정확한 문제를 해결하지는 않습니다.
쉘 스크립트에서 stderr로 리디렉션을 사용하는 경우:받아들인 대답은 내가 하는 경향이 있음을 보여줍니다. 즉, 프로그램의 최종 출력을 stdout에 유지하고 다른 모든 것을 stderr에 유지하는 것입니다. 그러나 이는 주장에 의해 뒷받침되기는 하지만 사용자 의견으로만 제시됩니다.
사용법 메시지를 stderr 또는 stdout으로 보내야 합니까?: 이는 도움말 메시지에만 적용되지만 GNU 코딩 표준을 참조합니다. 내가 찾고 있는 것은 단순한 도움말 메시지가 아니라 바로 이것이다.
그렇다면 진행 보고서 및 기타 정보 메시지(프로그램의 실제 출력의 일부가 아님)를 인쇄해야 하는 공식 규칙이 있습니까?
답변1
답변2
Posix는 표준 스트림을 정의합니다.그러므로:
프로그램이 시작되면 세 개의 스트림이 미리 정의되어야 하며 명시적으로 열 필요는 없습니다.표준 입력(일반 입력 읽기용)표준 출력(일반 출력 작성용) 및표준 에러(진단 출력 쓰기용) 열릴 때 표준 오류 스트림은 완전히 버퍼링되지 않습니다. 표준 입력 및 표준 출력 스트림은 표준 입력 및 표준 출력 스트림이 대화형 장치를 참조하지 않는다고 판단할 수 있는 경우에만 완전히 버퍼링됩니다.
이것GNU C 라이브러리표준 스트림도 비슷하게 설명됩니다.
바꾸다:문서*표준 출력
표준 출력 스트림은 프로그램의 일반 출력에 사용됩니다.바꾸다:문서*표준 에러
프로그램에서 발행한 오류 메시지 및 진단에 대한 표준 오류 스트림입니다.
따라서 표준에서는 "정규/정상 출력" 및 "진단/오류 출력" 이외의 스트림 사용에 대한 지침을 거의 정의하지 않습니다. 실제로 이러한 스트림 중 하나 또는 둘 다를 진행률 표시기가 문제가 되는 파일 및 파이프로 리디렉션하는 것이 일반적입니다. 일부 시스템은 심지어감시 장치 stderr
출력하고 이를 문제의 증상으로 간주합니다. 따라서 순수한 보조 진행 정보는 두 스트림 모두에서 문제가 됩니다.
무조건 진행률 표시기를 보내는 대신누구나표준 스트림에서는 진행 출력이 다음에만 적용된다는 점을 인식하는 것이 중요합니다.인터렉티브개울. 이를 염두에 두고 스트림이 대화형인지 확인한 후에만 진행률 카운터를 작성하는 것이 좋습니다(예:isatty()
) 또는 명령줄 옵션을 통해 명시적으로 활성화된 경우. 이는 완료율 표시줄과 같이 이해하기 위해 터미널 업데이트 동작에 의존하는 진행률 표시기의 경우 특히 중요합니다.
매우 간단한 진행 메시지의 경우("시작 이 경우 검색 grep
, 페이지 매김 less
또는 모니터링 에 사용하는 등 사용자가 흐름과 상호 작용하는 방식을 고려하세요 tail -f
. 이러한 상황에서 진행 메시지를 보는 것이 타당하다면 에서 읽기가 더 쉬울 것입니다 stdout
.
답변3
제외 원칙에 따라 stderr에만 액세스할 수 있습니다. 예, 귀하가 공식 사양을 요청했다는 것을 알고 있습니다. Stephen Kitt가 제공한 POSIX 사양에 대한 링크 외에는 stderr이 진단 목적으로 사용된다는 링크 외에는 제공할 수 없습니다.
더 중요한 점은 stdin과 stdout에는 진행 보고서가 stdout으로 인쇄되는 것을 허용하지 않는 기능이 있다는 것입니다. 물론 이들은 파이프 시퀀스를 형성합니다. 이는 Unix 쉘 명령의 부작용일 뿐만 아니라 강력한 파이프의 핵심입니다. 방법.
그래서. 프로그램의 실제 "페이로드"를 제외하고는 표준 출력에 속하지 않습니다. 프로그램에 출력이 없으면 표준 출력으로 아무 것도 보내면 안 됩니다. 이로 인해 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
파일과 내용이 혼동되었습니다 ...
답변4
사용자가 호출한 경우 --help
사용법 메시지를 stdout으로 보내야 하고, 사용자가 오류를 범한 경우 stderr로 보내야 합니다 . 무조건 stderr로 인쇄하는 것은 pager/grep/etc를 사용하여 보기 어렵게 만들기 때문에 성가신 일입니다.
또한 세 번째 접근 방식을 제안할 수 있습니다. 진행 보고서/스피너/등을 얻으려면 /dev/tty를 엽니다.