進捗レポート/ログ情報はstderrまたはstdoutに属しますか?


75

進捗レポートとログ情報(「Doing foo; foo done」など)を印刷する場所に関する公式のPOSIX、GNU、またはその他のガイドラインはありますか?個人的には、標準エラー出力にリダイレクトして、プログラムの実際の出力のみを取得できるように、標準エラー出力に書き込む傾向があります。最近、進捗レポートは実際にはエラーではなく、エラーメッセージのみがstderrに出力されるため、これは良い方法ではないと言われました。

両方のポジションが理にかなっており、もちろん、あなたがしていることの詳細に応じてどちらかを選択することができますが、これについて一般的に受け入れられている標準があるかどうか知りたいです。POSIX、GNUコーディング標準、またはその他の広く受け入れられているベストプラクティスのリストに特定のルールを見つけることができませんでした。

同様の質問がいくつかありますが、これらは正確な問題に対処していません。

それでは、進捗レポートやその他の情報メッセージ(プログラムの実際の出力の一部ではない)を印刷する場所に関する公式ルールはありますか?


26
stdout結果と一緒にスピナーなどを印刷することは、結果を役に立たなくする安全な方法です。結果を他のプログラムにパイプする必要がある場合、そのプログラムは結果をスピナーから分離する必要があります。また、出力をファイルにリダイレクトすると、スピナーを見ることができなくなります。私見では。
桂佐藤

2
@SatoKatsuraええ、それは私の意見でもあり、それが私がstderrにそのようなものを印刷する理由です。しかし、私が働いている会社のCTOは、stderrへの印刷は何かがうまくいかなかったことを示していると感じています。POSIXWay®がstderrに印刷されていると、かなり大胆に主張しました。彼が私に20年の奇妙な経験を持っていることを考えると、ある種の「公式」ガイドラインを見つけることができるかどうかを見たいです。
テルドン

佐藤桂が言ったように、stdout実際にはスピナーやその他の有益なメッセージを削除する安全で正しい方法ですが、多くのプログラマーは「沈黙は黄金です。すべてが正常な場合は何も出力しません。」そう実際には、標準エラー出力は常にsequence.forパイプ壊れる可能性もSTDOUTという理由あいまいな定義で行うために使用され、 公式ガイド
VENのSeを

6
@Sevenあなたは誤解したと思います。佐藤は、stdoutの使用は安全でないと言っています(「結果を役に立たない安全な方法」)。
スティーブンキット

1
1つの万能ソリューションの1つはstderr--verboseフラグが使用されている場合を除き、エラーメッセージの報告にのみ使用することです。この場合、進捗レポートも含まれます。
ガウラブ

回答:


27

Posixは標準ストリーム次のように定義します:

プログラムの起動時に、標準入力(従来の入力を読み取るため)、標準出力(従来の出力を書き込むため)、および標準エラー(診断出力を書き込むため)の3つのストリームを事前に定義し、明示的に開く必要はありません。開いたとき、標準エラーストリームは完全にバッファリングされていません。ストリームが対話型デバイスを参照しないと判断できる場合にのみ、標準入力および標準出力ストリームは完全にバッファリングされます。

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。後者はファイルにリダイレクトされるときにデバッグに使用されるため、常に保持する必要があります。したがって、ストリームがインタラクティブであるかどうかを確認するという提案は当てはまりません(ただし、一般的には非常に良い考えです)。
テルドン

わかりやすいおかげで、「%complete」のようなものcurlや、やなどのソフトウェアに表示されるハッシュマークの進行状況バーとは少し異なりますyum。その場合、ユーザーがgreplessまたは同様のツールを介して出力とやり取りするかどうか、およびその方法を考えます。
ブラッドゾニエ16

上記の説明を組み込むために回答を更新しました。
ブラッドゾニエ16

71

POSIX は標準エラーを次のように定義します

診断出力を書き込むため

これは、エラーメッセージのみに使用を制限するものではありません。進捗情報を診断出力と見なすため、標準エラーに属します。


8
PythonでFWIWは、stdout一方のラインバッファリングデフォルトではstderrバッファリングされていないので、stderr改行が含まれていない進行状況テキスト/バー/スピナーを書くための自然な選択です。(このようなテキストを書く場合stdoutは、表示stdout.flush()するために進行状況の出力呼び出しを煩雑にする必要があります)。
PM 2Ring 16

12
Pythonに固有ではない@ PM2Ring、POSIXはストリームをそのように定義します。
スティーブンキット

4
@ PM2Ring:に書き込むときにstdout、進行状況レポートをリダイレクト時にリアルタイムで実際に表示するには、テキストに改行含まれている場合でもフラッシュする必要があります。

@Hurkyl Ah、良い点。リダイレクトを検討していませんでした。
PM 2Ring 16

1
@Wtower、え?いいえ。終了ステータスが0の場合、Ansibleはstderrテキストを飲み込みます。その主張は単純に偽です。
チャールズダフィー

10

POSIXは、Shell and Utilitiesの「診断情報」、1.4:Utility Description Defaults(emphasis mine)についてもう少し具体的です。

STDERR

STDERRセクションでは、ユーティリティの標準エラー出力について説明しています。ユーティリティによって意図的に送信されるメッセージのみが説明されています。標準エラー用の端末を使用すると、標準エラー出力を書き込む標準ユーティリティがバックグラウンドで使用されると停止する場合があります。このため、アプリケーションは、スクリプトでインタラクティブ機能を使用してバックグラウンドに配置しないでください。

ほとんどのユーティリティの診断メッセージの形式は指定されていませんが、POSIX.1-2008のこのボリュームで形式が指定されていない診断および情報メッセージの言語および文化的慣習は、LC_MESSAGESおよび[XSI] [Option Start ] NLSPATH。[オプション終了]

標準ユーティリティの指定された標準エラー出力は、このPOSIX.1-2008のボリュームで提供されている場合を除き、このPOSIX.1-2008のボリュームで定義されている環境変数の存在または値に依存してはなりません。

デフォルトの動作:このセクションが「標準エラーは診断メッセージにのみ使用される」と記載されている場合、特に明記しない限り、終了ステータスがエラーを示す場合にのみ診断メッセージが標準エラーに送信されることを意味します発生したとPOSIX.1-2008のこの体積により記載されるようにユーティリティが使用されています。

このセクションが「使用しない」と表示されている場合、POSIX.1-2008のこのボリュームで説明されているようにユーティリティを使用する場合、標準エラーを使用しないことを意味します。

IANASLですが、ユーティリティがエラー終了コードを返す場合にのみstderrが出力することを意味すると解釈します。これは正常に実行されるための通常のイベントではないため、エラーが発生しない限り、POSIXユーティリティは進捗情報を出力しません(もちろん、特に指定がない限り)。


これは、標準エラーの使用法の一般的な定義としてではなく、各POSIXユーティリティの仕様にある「STDERR」セクションの意味を説明するものとして理解しています。terdonが標準POSIXユーティリティをここで書いているとは思わない;-)。
スティーブンキット

1
@StephenKittも私ではありません。しかし、彼は彼のCTOと議論しています。
ムル16

1
POSIXユーティリティのデフォルト動作としてのクレームのみをサポートし、特定の場合(言及されたフレーズを使用するユーティリティ)でもサポートします。POSIXのこの部分は規範的(AIUI)ではなく、テンプレートです。ユーティリティの仕様の読み方を示し、ユーティリティの動作を指定しません。具体的には、「標準エラーは診断メッセージにのみ使用される」というフレーズの意味を定義しています。および「使用されません。」ユーティリティ仕様の「STDERR」セクション。各ユーティリティはその動作を指定し、それらのフレーズを省略形として使用できます。
スティーブンキット

@StephenKittは私のポイントを変えません。POSIXユーティリティは、a)stderrに出力しない、b)問題が発生した場合に診断メッセージのみに使用する、c)何も問題がなくても診断メッセージのみに使用する、d)他の何かに使用する。特に明記されていない限り(c、d)、何か問題が発生した場合(a、b)にのみ診断メッセージに使用すると述べました。さて、私の主張は、これがデフォルトであるということです。それがテンプレートである理由だからです。
ムル16

2
まあ、「特に指定しない限り」はかなり重要な警告だと思います。POSIXユーティリティは、標準エラーに関する進捗情報を出力し、標準に準拠することを指定できます。正しいのは、終了コードもエラーを示している場合にのみ、「デフォルトの動作」(関連セクションで特定の言及が必要です)が標準エラーのみを使用することです。しかし、それは制限ではありません。
スティーブンキット

7

除外の原則により、stderrにのみ移動できます。はい、私はあなたが公式仕様について尋ねたのを知っています、stderrは診断目的のためであると述べるStephen Kittによって与えられたPOSIX仕様へのリンクを超えてあなたに提示することはできません。

より重要な点は、stdinおよびstdoutには、stdoutへの進行状況レポートの印刷を許可しない機能があることです。もちろん、Unixシェルコマンドでは単なる副作用ではなく、強力なパイプライニングアプローチのコアであるパイプのシーケンスを形成します。

そう。プログラムの実際の「ペイロード」以外は、stdoutに属しません。プログラムに出力がない場合、何もstdoutに送られません。これにより、進行状況レポートを含む他のすべてのものが標準エラーになります

確かに、これは穴を残します-「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?3番目のフロッピーディスク?
ピーターモーテンセン

ファイル記述子3、@ PeterMortensen
AnoE

-1

使用法メッセージは、ユーザーが呼び出した場合はstdoutに--help、間違いを犯した場合はstderrに送信する必要があります。stderrに無条件に印刷すると、ページャー/ grep / etcで表示するのが難しくなるため、不快です。

また、3つ目の方法を提案できます。/dev/ttyを開いて、進捗レポート/スピンナー/などを確認します。


6
申し訳ありませんが、これは質問に答えていません。意見ではなく、公式のガイドラインを具体的に求めました。いずれにせよ、私が意見を求めたとしても、あなたは別の質問に答えています。--helpメッセージについて話したり、メッセージを手助けしたりすることはまったくありません。質問を読み直してください。
テルドン

あなたは「使用法メッセージ」に言及しましたが、それはあなたがリンクした他の質問のタイトルではなく、あなたの質問の一部だと思いました。このために「公式ガイドライン」が存在すると考える理由がわかりません。誰がそれらを作る権限を持っているでしょうか?
Random832 16

3
私は彼らがそうすることを知りません、それが私が尋ねる理由です。公式に関しては、POSIX標準には、プログラムの動作方法に関するさまざまな詳細についての仕様があります。ステファンが彼の答えで指摘したように、stderrに何をすべきかについてのあいまいな提案を含む。GNUコーディング標準にも同様のものがあります。基本的には、中にアクティブであり、* nixの生態系のためのコードを生成する任意のグループは、私が興味があると思い標準を持っているかもしれません。
terdonの

@terdon既存のプログラムが何をするかの例で大丈夫でしょうか?curl、wget、およびpvはすべてstderrを使用し、wgetとpvはttyであることが条件になり、curlはstdoutがttyではないことを条件にします。
Random832 16

4
また、それはのように聞こえるあなたのCTOは、呼び出し元のプログラムではなく、終了ステータスを見ているよりも、エラーが発生したことを意味するとstderrにデータの存在に反応するべきであると考えています。これは間違いなく悪い習慣であり(また、終了ステータスをチェックするよりも書くのが難しい)、彼を納得させるのにより良い角度かもしれません。
Random832 16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.