注文されたSTDOUT / STDERRをキャプチャし、タイムスタンプ/プレフィックスを追加する方法は?

注文されたSTDOUT / STDERRをキャプチャし、タイムスタンプ/プレフィックスを追加する方法は?

ほぼ全部探索してみたみんな 書くことができる 似たような 質問、役に立たない。

この問題について詳しく説明します。

stdout行とstderr行を生成する無人スクリプトを実行し、それをキャプチャしたいと思います。端末エミュレータに表示されている正確な順序に従ってください。次に、「STDERR:」や「STDOUT:」などの接頭辞を追加します。

私はパイプとepollベースの方法を試しましたが、成功しませんでした。私はこの分野の専門家ではありませんが、解決策はptyの使い方にあると思います。ソースコードも見ました。GNOME用VTEしかし、これはあまり効果がありませんでした。

理想的には行くこれを行うために、Bashの代わりに私はそれをすることができませんでした。バッファリングによってパイプが正しいライン順序を維持することは自動的に禁止されるようです。

似たようなことができる人はいますか?それともこれは不可能ですか?私の考えでは、ターミナルエミュレータがこれを行うことができれば、それはできません。おそらく、PTYを別の方法で処理する小さなCプログラムを作成するのではないでしょうか?

理想的には、非同期入力を使用して両方のストリーム(STDOUTとSTDERR)を読み込み、必要に応じて再印刷しますが、入力順序は重要です!

メモ:わかりましたストライディッドただし、Bashスクリプトでは機能しないため、プレフィックスを追加するために簡単に編集することはできません(デフォルトでは複数のシステムコールをラップするため)。

修正する:次の2つを追加しました。

(一貫した結果を示すために、私が提供したサンプルスクリプトに1秒未満のランダム遅延を追加できます。)

修正する:この問題に対する解決策も解決されます。これは別の質問です、@Gillesが指摘したように。しかし、私は次の結論に達しました。不可能あちこちで要求どおりに行ってください。 2つのストリームを使用している場合は、2>&1pty / pipeレベルで正しくマージされますが、ストリームを個別に正しい順序で使用するには、実際には次の方法を使用する必要があります。ストライディッド次のように表示されるシステムコールフックが含まれています。汚いあらゆる点で。

誰もが上記のポイントに反論できる場合は、喜んで質問を更新します。

ベストアンサー1

コルーチンも使用できます。マークアップを実行する2つのsedインスタンス(もう一方はstderr他方)に指定されたコマンドの2つの出力を提供する単純なラッパーです。stdout

#!/bin/bash
exec 3>&1
coproc SEDo ( sed "s/^/STDOUT: /" >&3 )
exec 4>&2-
coproc SEDe ( sed "s/^/STDERR: /" >&4 )
eval $@ 2>&${SEDe[1]} 1>&${SEDo[1]}
eval exec "${SEDo[1]}>&-"
eval exec "${SEDe[1]}>&-"

いくつかの点に注意してください。

  1. 私を含む多くの人にとって、これは何らかの理由で魔法の呪文です(下記のリンクされた答えを参照)。

  2. 時々、数行を変更しないという保証はありません。共同プロセスのスケジュールによって異なります。実際、いつか、そのようなことが起こることはほぼ確実です。つまり、順序が厳密に同じままである場合は、両方のプロセスのデータを同じプロセスで処理する必要がありますstderrstdinそうしないと、カーネルスケジューラがこれを台無しにする可能性があります。

    質問が正しく理解されている場合は、2つのストリームを1つのプロセスにリダイレクトするようにシェルに指示する必要があります(これは完了することができることを理解しています)。問題は、プロセスが最初に何を行うかを決定し始めたときに始まります。プロセスは2つのデータソースをポーリングする必要があり、ある時点で1つのストリームが処理され、データが完了する前に両方のストリームに到達する状態になります。これが崩れるところです。これはまた、このような出力システムコールをラップすることがstderred望ましい結果を得る唯一の方法である可能性があることを意味します(そしてそのような場合でも、マルチプロセッサシステムでマルチスレッドになると問題が発生する可能性があります)。

共同プロセスについては、Stéphaneの記事を必ずお読みください。Bashでcoprocコマンドを使用する方法は?深い洞察力を得るためです。

おすすめ記事