進行状況レポート/ログ情報はstderrまたはstdoutに属していますか?

進行状況レポート/ログ情報はstderrまたはstdoutに属していますか?

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

どちらの立場にも意味があり、もちろん、実行している作業の詳細に応じて、どちらかを選択できますが、それについて一般的に認められている標準があるかどうか疑問に思います。 POSIX、GNUコーディング標準、または他の広く認められているベストプラクティスのリストに特定のルールがありません。

同様の質問がいくつかありますが、正確な問題を解決するわけではありません。

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

答え1

POSIX標準誤差を次のように定義します。

診断出力書き込み用

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

答え2

Posix は標準ストリームを定義します。だから:

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

これGNU Cライブラリ標準ストリームも同様に記述される。

変える:文書*標準出力
標準出力ストリームは、プログラムの通常出力に使用されます。

変える:文書*標準エラー
プログラムによって発行されたエラーメッセージと診断の標準エラーストリーム。

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

無条件の進行状況インジケータを送信する代わりに誰でも標準ストリームでは、進行出力が次にのみ適用されることを認識することが重要です。インタラクティブ小川。これを念頭に置いて、ストリームが対話型であることを確認した後にのみ進行状況カウンタを作成することをお勧めします(例:isatty())またはコマンドラインオプションで明示的に有効になっている場合。これは、完了率バーなど、理解するために端末の更新動作に依存する進行状況インジケータにとって特に重要です。

非常に単純な進捗メッセージの場合(「この場合は、検索grep、ページ付け、またはless監視に使用するなど)、ユーザーがフローと対話する方法を検討してください。。tail -fstdout

答え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を使用して見にくくするので面倒です。

また、3番目のアプローチを提案できます。進行状況レポート/スピナー/などを取得するには、/dev/ttyを開きます。

関連情報