stderrとstdoutをそれぞれbashスクリプトの関数にリダイレクトする

stderrとstdoutをそれぞれbashスクリプトの関数にリダイレクトする

頑張っていますラッパースクリプトcronjob 出力を記録します。

私はいくつかの目標を持っています:

  • stderrとstdoutは、異なる優先順位とプレフィックスラベルを使用して記録する必要があります。
  • また、ラップされたコマンドのstderrをラッパースクリプトのstderrに出力する必要があります(cronでキャプチャして電子メールで警告します)。
  • 行の順序は常に維持する必要があります

これまでに2つの問題があるようです。

  1. stderrとstdoutを別々にロギング機能にリダイレクトする方法がわかりません。これまで試したことはすべて、NULL以外をリダイレクトできませんでした。私の考えでは、リダイレクトは私の利点の1つではありません。(解決済み、コメントを参照)
  2. 私の現在のアプローチ{ $_EXEC $_ARGS 2>&1 1>&7 7>&- | journaldlog error; } 7>&1 1>&2 | journaldlog infoは、ロギング機能を2回(stderrに対して1回、stdoutに対して1回)実行するようです。これにより、行の順序は維持されません。むしろ、出力ラインごとに一度だけ関数を実行したいと思います。

bashでこれを放棄し、Perlを試すべきですか?私はPerlの経験が最終的に戻ってくると確信しています。

私は様々なことを試しました。これらのほとんどはオンライン、特にStack Exchangeで見つけることができます。私は正直、私が何をしようとしたのか覚えていません。この時点では、ぼやけているだけです。そしてbashドキュメントはあまり役に立ちません。

ベストアンサー1

ただ使えますプロセスの交換リダイレクトから直接:

gen > >(one) 2> >(two)

これにより、標準出力がgen標準入力として提供され、one標準エラーがgen入力として提供されますtwo。実行可能なコマンドまたは関数にすることができます。私が使用する機能は次のとおりです。

one() {
    while read line
    do
        echo $'\e[31m'"$line"$'\e[22m'
    done
}

two() {
    while read line
    do
        echo $'\e[32m'"$line"$'\e[22m'
        echo "$line" >&2
    done
}

入力ラインをそれぞれ赤と緑に出力し、two通常の標準エラーにも記録します。ループ内で必要なものは何でもでき、入力を他のプログラムや必要なものに送信できます。


気づくこの時点まで、「行順の維持」などの実用的な機能はありません。- 2つの独立したストリームと独立したプロセス。スケジューラはしばらくの間プロセスを実行し、別のプロセスを実行し、データは読み取られるまでカーネルパイプバッファに保持されます。私はテストのために奇数をstdoutとstderrに出力する関数を使用してきました。

端末に表示されているものに近い注文を取得できますが、Bashの注文ではない可能性があります。交換プログラムの使い方pipeそしてselectシーケンスを再構成することは可能です(表示されているものと同じであることを保証することはできませんが、同じ理由でプロセスがしばらくスケジュールされない可能性があり、バックログが発生すると最初に何が起こったかを知る方法はありません1 )。。順序が重要な場合は、他のアプローチが必要であり、基本実行可能ファイルの共同作業も必要になる場合があります。これが難しい要件であれば、在庫してみることをお勧めします。

1パイプバッファリングを制御するプラットフォーム固有の方法があるかもしれませんが、この方法も十分に役に立ちません。 Linuxでは、バッファサイズをシステムページサイズに減らすことができますが、それを下げることはできません。私はすぐに書き込みを強制できる(または読むまでブロックできる)機能を知りません。それにもかかわらず、ソースからstdioストリームにバッファリングされる可能性が高いため、ソートは表示されません。

おすすめ記事