it-swarm.com.de

Gehören Fortschrittsberichte / Protokollierungsinformationen zu stderr oder stdout?

Gibt es eine offizielle POSIX-, GNU- oder andere Richtlinie, in der Fortschrittsberichte und Protokollinformationen (z. B. "Doing foo; foo done") gedruckt werden sollen? Persönlich neige ich dazu, sie an stderr zu schreiben, damit ich stdout umleiten und nur die tatsächliche Ausgabe des Programms erhalten kann. Mir wurde kürzlich gesagt, dass dies keine gute Praxis ist, da Fortschrittsberichte eigentlich keine Fehler sind und nur Fehlermeldungen an stderr gedruckt werden sollten.

Beide Positionen sind sinnvoll, und natürlich können Sie je nach den Details Ihrer Tätigkeit die eine oder die andere auswählen, aber ich würde gerne wissen, ob es dafür einen allgemein akzeptierten Standard gibt. Ich konnte keine spezifischen Regeln in POSIX, den Codierungsstandards GNU) oder anderen allgemein akzeptierten Listen von Best Practices finden.

Wir haben einige ähnliche Fragen, die jedoch nicht genau dieses Problem ansprechen:

Gibt es offizielle Regeln, nach denen Fortschrittsberichte und andere informative Nachrichten (die nicht Teil der tatsächlichen Ausgabe des Programms sind) gedruckt werden sollen?

79
terdon

Posix definiert die Standard-Streams also :

Beim Programmstart müssen drei Streams vordefiniert sein und müssen nicht explizit geöffnet werden: Standardeingabe (zum Lesen herkömmlicher Eingaben), Standardeingabe (zum Schreiben) konventionelle Ausgabe) und Standardfehler (zum Schreiben der Diagnoseausgabe). Beim Öffnen wird der Standardfehlerstrom nicht vollständig gepuffert. Die Standardeingabe- und Standardausgabestreams werden genau dann vollständig gepuffert, wenn festgestellt werden kann, dass sich der Stream nicht auf ein interaktives Gerät bezieht.

Die GNU C Library beschreibt die Standard-Streams ähnlich:

Variable: [~ # ~] Datei [~ # ~] * stdout
Der Standardausgabestream, der für die normale Ausgabe des Programms verwendet wird.

Variable: [~ # ~] Datei [~ # ~] * stderr
Der Standardfehlerstrom, der für vom Programm ausgegebene Fehlermeldungen und Diagnosen verwendet wird.

Daher haben Standarddefinitionen nur wenige Richtlinien für die Verwendung von Streams, die über "konventionelle/normale Ausgabe" und "Diagnose-/Fehlerausgabe" hinausgehen. In der Praxis ist es üblich, einen oder beide dieser Streams in Dateien und Pipelines umzuleiten, wo Fortschrittsindikatoren ein Problem darstellen. Einige Systeme haben sogar monitorstderr für die Ausgabe und betrachten dies als Zeichen von Problemen. Rein zusätzliche Fortschrittsinformationen sind daher in beiden Streams problematisch.

Anstatt Fortschrittsindikatoren bedingungslos an entweder Standard-Stream zu senden, ist es wichtig zu erkennen, dass die Fortschrittsausgabe nur für interaktiv Streams geeignet ist. In diesem Sinne empfehle ich, Fortschrittszähler nur zu schreiben, nachdem überprüft wurde, ob der Stream interaktiv ist (z. B. mit isatty() ) oder wenn dies explizit durch eine Befehlszeilenoption aktiviert wird. Dies ist besonders wichtig für Fortschrittsanzeigen, bei denen das Verhalten der Terminalaktualisierung sinnvoll ist, z. B.% -vollständige Balken.

Für bestimmte sehr einfache Fortschrittsmeldungen ("X starten" ... "Fertig mit X") ist es sinnvoller, die Ausgabe auch für nicht interaktive Streams einzuschließen. Überlegen Sie in diesem Fall, wie Benutzer mit den Streams interagieren könnten, z. B. mit grep suchen oder mit less blättern oder mit tail -f Überwachen. Wenn es sinnvoll ist, die Fortschrittsmeldungen in diesen Kontexten anzuzeigen, können sie viel einfacher von stdout verwendet werden.

28
Bradd Szonye

POSIX definiert Standardfehler als

zum Schreiben der Diagnoseausgabe

Dies beschränkt seine Verwendung nicht nur auf Fehlermeldungen. Ich würde Fortschrittsinformationen als Diagnoseausgabe betrachten, daher gehören sie zum Standardfehler.

74
Stephen Kitt

POSIX ist etwas konkreter in Bezug auf "Diagnoseinformationen" in Shell and Utilities, 1.4: Utility Description Defaults (Hervorhebung von mir):

STDERR

Der Abschnitt STDERR beschreibt die Standardfehlerausgabe des Dienstprogramms. Es werden nur die Nachrichten beschrieben, die vom Dienstprogramm absichtlich gesendet werden. Die Verwendung eines Terminals für Standardfehler kann dazu führen, dass eines der Standarddienstprogramme, die die Standardfehlerausgabe schreiben, im Hintergrund angehalten wird. Aus diesem Grund sollten Anwendungen keine interaktiven Funktionen in Skripten verwenden, die im Hintergrund platziert werden sollen.

Das Format der Diagnosemeldungen für die meisten Dienstprogramme ist nicht angegeben, aber die sprachlichen und kulturellen Konventionen der Diagnose- und Informationsnachrichten, deren Format in diesem Band von POSIX.1-2008 nicht angegeben ist, sollten durch die Einstellung von LC_MESSAGES und [XSI] [Option Start] beeinflusst werden ] NLSPATH. [Optionsende]

Die angegebene Standardfehlerausgabe von Standarddienstprogrammen hängt nicht von der Existenz oder dem Wert der Umgebungsvariablen ab, die in diesem Volume von POSIX.1-2008 definiert sind, es sei denn, dies wird in diesem Volume von POSIX.1-2008 bereitgestellt.

Standardverhalten : Wenn dieser Abschnitt als "Der Standardfehler darf nur für Diagnosemeldungen verwendet werden" aufgeführt ist, bedeutet dies, dass, sofern nicht anders angegeben, Die Diagnosemeldungen werden an den Standardfehler gesendet. nur wenn der Exit-Status anzeigt, dass ein Fehler aufgetreten ist und das Dienstprogramm ist wird wie in diesem Band von POSIX.1-2008 beschrieben verwendet.

Wenn dieser Abschnitt als "Nicht verwendet" aufgeführt ist, bedeutet dies, dass der Standardfehler nicht verwendet werden darf, wenn das Dienstprogramm wie in diesem Band von POSIX.1-2008 beschrieben verwendet wird.

IANASL, aber ich interpretiere das so, dass stderr nur ausgegeben wird, wenn das Dienstprogramm einen Fehler-Exit-Code zurückgibt. Da dies nicht der normale Ablauf von Ereignissen für eine erfolgreiche Ausführung sein sollte, sollten keine Fortschrittsinformationen von einem POSIX-Dienstprogramm gedruckt werden, es sei denn, ein Fehler tritt auf (es sei denn, von natürlich anders angegeben usw.).

10
muru

Nach dem Ausschlussprinzip kann es nur an stderr gehen. Ja, ich weiß, dass Sie nach einer offiziellen Spezifikation gefragt haben, die ich Ihnen nicht über den Link zur POSIX-Spezifikation von Stephen Kitt hinaus präsentieren kann, der besagt, dass stderr für diagnostische Zwecke bestimmt ist.

Der wichtigere Punkt ist, dass stdin und stdout eine Funktion haben, die das Drucken von Fortschrittsberichten an stdout nicht zulässt - sie bilden natürlich die Folge von Pipes, die in Unix Shell-Befehlen nicht nur ein Nebeneffekt ist, sondern den Kern des leistungsstarken Pipelining-Ansatzes darstellt .

Damit. Nichts außer der tatsächlichen "Nutzlast" Ihres Programms gehört zu stdout. Wenn Ihr Programm keine Ausgabe hat, sollte nichts zu stdout gehen. Dies lässt stderr für alles andere, einschließlich Fortschrittsberichte.

Zugegeben, dies hinterlässt ein Loch - es wäre wahrscheinlich schön, einen "stdfluff" oder ähnliches zu haben, der weder für Ausgabe noch für Fehler, sondern für Fortschrittsberichte, Debugging und dergleichen bestimmt ist. Tatsächlich hindert Sie nichts daran, d. H. Sie könnten Ihren Fortschritt in Dateideskriptor 3 drucken. Beispiel:

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

Dies erzeugt keine Ausgabe. (*)

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

Dies wird auf fd-3 gedruckt, das zu stdout umgeleitet wird.

(*) Das erste Beispiel erzeugt keine Ausgabe, ist aber immer noch etwas weit hergeholt. das open schlägt fehl und $! würde no such file or directory enthalten; Nehmen Sie dies nur als Beispiel, es ist natürlich nicht erwähnenswert, so ernsthaft verwendet zu werden. Wenn Sie in einem tatsächlichen Programm diesen Weg gehen möchten, können Sie testen, ob /dev/fd/3 Verwendbar ist, und dies als Hinweis darauf verwenden, ob Sie Ihre Fortschrittsberichte aktivieren möchten. Sie müssten das ziemlich früh tun, damit Sie nicht durch Ihre eigenen opens für echte Dateien und dergleichen verwirrt werden ...

9
AnoE