stdoutとstderrをファイルにリダイレクトし、stderrをコンソールに表示する方法は?

stdoutとstderrをファイルにリダイレクトし、stderrをコンソールに表示する方法は?

私はファイルにリダイレクトし、基本レベルでteeを使用する方法を知っています。だから

$ alias outanderr='bash -c "echo stdout >&1; echo stderr >&2"'
# A fake "application" displaying both output and error messages.

$ outanderr 1>file      # redirect stdout to a file, display stderr
stderr

$ outanderr 2>file      # redirect stderr to a file, display stdout
stdout

$ outanderr 1>file 2>&1 # redirect both to a file, display nothing

$ outanderr | tee file; echo "-- file contents --" && cat file
# redirect stdout to a file, display both (note: order is messed up)
stderr
stdout
-- file contents --
stdout

$ outanderr 2>&1 | tee file; echo "-- file contents --" && cat file
# redirect both to a file, display both
stdout
stderr
-- file contents --
stdout
stderr

問題は、次のような結果を得るために疑問符の代わりに何を書くべきかです。

$ outanderr ???; echo "-- file contents --" && cat file
# redirect both to a file, display stderr
stderr
-- file contents --
stdout
stderr

要素:

  • バッシュを想定します。
  • 注文はファイルに保存する必要があります。
  • stderrの内容は、バッファリングなしでリアルタイムで1行ずつ表示されます。
  • 別のスクリプトファイルを使用できます。
  • 魔法が必要な場合があります。

ベストアンサー1

2>&1 >>outputfile | tee --append outputfile

テストを容易にするには:

echo -n >outputfile; bash -c "echo stdout >&1; echo stderr >&2" 2>&1 >>outputfile |
  tee --append outputfile; echo "outputfile:"; cat outputfile

編集1:

これは、ファイルにstdout(専用)を作成し、sterr stdoutをパイプにし、teeに出力を同じファイルに書き込むことによって行われます。

>>両方の書き込みは追加モード(追加モードではありません)で実行する必要があります>。それ以外の場合は、両方が互いに出力を上書きします。

パイプはバッファなので、出力がファイルに正しい順序で表示されるという保証はありません。アプリケーションが2つのファイル記述子(2つのパイプ)に接続されていても、これは変わりません。順序を保証するには、両方の出力が同じチャネルを通過し、別々にタグ付けする必要があります。それとも本当に素晴らしいものが必要です。

  1. stdoutとstderrの両方がファイル(同じファイルではありません!)にリダイレクトされ、両方のファイルがFUSEボリュームにある場合、FUSEモジュールは各書き込みにタイムスタンプをスタンプして、2番目のアプリケーションがデータを正しく解析できるようにします。 。実際の出力ファイルとして。または、データにラベルを付けずに、モジュールに結合された出力ファイルを生成させます。おそらく、まだこれを行うことができるFUSEモジュールはありません。
  2. stdoutとstderrの両方/dev/null。アプリケーションの出力はdetachを通過しますstrace -f -s 32000 -e trace=write。この場合、脱出をキャンセルする必要があります。言うまでもなく、アプリは追跡されるため、より速く実行されません。
  3. おそらく、既存の単純なFUSEモジュールを使用してアプリケーションの代わりにモジュールを追跡すると、同じ効果が得られます。これは、モジュールがアプリケーションよりもはるかに少ないシステムコールを持つ可能性があるため、アプリケーションを追跡するよりも高速です。
  4. アプリケーション自体を変更できる場合:アプリケーションはすべての出力後に停止することができます(ただしこれは内部でのみ実行できると思います)、信号(SIGUSR1またはSIGCONT)を受信した後にのみ続行できます。パイプから読み取るアプリケーションは、パイプとファイルで新しいデータを確認し、新しいデータが出るたびにシグナルを送信する必要があります。アプリケーションの種類に応じて、これはstraceメソッドよりも高速または遅くなる可能性があります。 FUSEが最速のソリューションになります。

おすすめ記事