web-dev-qa-db-ja.com

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

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

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

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

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

79
terdon

Posixは標準ストリームを定義します したがって

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

GNU Cライブラリ は、標準ストリームを同様に記述します。

変数:[〜#〜]ファイル[〜#〜]*stdout
プログラムからの通常の出力に使用される標準出力ストリーム。

変数:[〜#〜]ファイル[〜#〜]*stderr
プログラムによって発行されたエラーメッセージと診断に使用される標準エラーストリーム。

したがって、標準的な定義では、「従来の/通常の出力」および「診断/エラーの出力」以外のストリームの使用に関するガイダンスはほとんどありません。実際には、これらのストリームのいずれかまたは両方をファイルおよびパイプラインにリダイレクトするのが一般的です。進行状況インジケーターが問題になります。一部のシステムでは、出力用にmonitorstderrを使用し、それを問題の兆候と見なしています。したがって、純粋に補助的な進捗情報は、どちらのストリームでも問題があります。

進行状況インジケーターを無条件にone標準ストリームに送信するのではなく、進行状況の出力はinteractiveストリームにのみ適切であることを認識することが重要です。そのことを念頭に置いて、ストリームがインタラクティブであるかどうか(たとえば isatty() )を確認した後、またはコマンドラインオプションで明示的に有効にした場合にのみ、進行状況カウンターを書き込むことをお勧めします。これは、%完了バーのように、端末の更新動作に依存する意味のある進行状況メーターで特に重要です。

特定の非常に単純な進行メッセージ(「Starting X」...「Done with X」)の場合、非インタラクティブストリームの場合でも出力を含める方が合理的です。その場合は、grepを使用した検索やlessを使用したページング、tail -fを使用した監視など、ユーザーがストリームを操作する方法を検討してください。これらのコンテキストで進行状況メッセージを表示することが理にかなっている場合は、stdoutからのほうがはるかに使いやすくなります。

28
Bradd Szonye

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

診断出力を書き込むため

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

74
Stephen Kitt

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

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ユーティリティによって進行情報は出力されません(ただし、もちろん、特に明記されていない場合など)。

10
muru

除外の原則により、それはstderrにしか行くことができません。はい、stderrは診断目的であると述べている、Stephen KittによるPOSIX仕様へのリンクを超えて提示することはできませんが、正式な仕様について尋ねたことを知っています。

より重要な点は、stdinとstdoutに、進行状況レポートをstdoutに出力することを許可しない機能があることです。もちろん、これらはパイプのシーケンスを形成します。これは、Unix Shellコマンドでは副作用だけでなく、強力なパイプラインアプローチの核心です。 。

そう。プログラムの実際の「ペイロード」以外は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

これは、stdoutにリダイレクトされるfd-3に出力されます。

(*)最初の例は出力を生成しませんが、まだ少し遠いです。 openは失敗し、$!にはno such file or directoryが含まれます。これを例にとると、もちろん、このように本格的に使用することはできません。実際のプログラムでは、この方法を使用したい場合は、/dev/fd/3が使用可能かどうかをテストし、これを進捗レポートをアクティブ化するかどうかのヒントとして使用できます。実際のファイルなどの独自のopensに混乱しないように、かなり早い段階でそれを行う必要があります...

9
AnoE