順序を変更せずに標準エラー出力を複製してbashで標準エラー出力とマージする


2

標準エラー出力と標準出力の両方をログファイルに書き出し、標準エラー出力を端末(またはデフォルトの出力デバイス)に出力します。

動機: 私は自分のcrontabにコマンドがあります、そして、私はその出力の全てをファイルに記録したいです、そして、エラー出力に書かれた何かがあれば私に電子メールを送りたいです。

私はこれらでいくらか成功しました:

(echo out1; echo err1 1>&2; echo out2; echo err2 1>&2) \
    2> >(tee -a log) \
    1>>log

または

(echo err1 1>&2; echo out2; echo err2 1>&2) \
    3>&1 \
    1> >(tee -a log 1>/dev/null) \
    2> >(tee -a log 1>&3)

またはexecで:

exec 3>&1
exec 1> >(tee -a log2 1>/dev/null)
exec 2> >(tee -a log2 1>&3)
echo out1; echo err1 1>&2; echo out2; echo err2 1>&2

(3番目の方法でもプロンプトがログに記録されるため、対話型シェルでは機能しません。)

3つの解決策すべての問題は、ログファイルの行が異なる順序で含まれていることです。

out1
out2
err1
err2

これの代わりに:

out1
err1
out2
err2

これを防ぐ方法はありますか?何かのようなもの 2>&1これは、ディスクリプタではなく、出力自体を複製します。

非常に似ている 質問 Windows用



はい、すみません、それは見つかりませんでした。他の質問は別のドメインにあるため、質問に重複のフラグを立てることはできません。どうすればよいですか。ちなみに、このようなもののためのきれいな解決策がないことは私にとってやや驚くべきことです
TPE

あなたはそれを投稿していないので、クロス投稿ではありません。それなら心配はありません。そのままにしてください。問題の問題に関しては、それが見えるかもしれないほど驚くべきことではありません。それは簡単です。 STDERRとSTDOUTは2つの異なるチャネルであり、それらを同期させるとコストがかかります。同期されていない、または共通ログでエラーの兆候がないかどうかを確認する方法を考えることができます grep または似たようなもの。
Tomasz

回答:


0

可能な限りこれを単純化し最適化したいと思います。私は今それを一歩一歩進めることよりも良い解決策を考えることはできません。すなわち

$ echo out1 >> log
$ echo err1 | tee -a log >&2
err1
$ echo out2 >> log
$ echo err2 | tee -a log >&2
err2
$ cat log
out1
err1
out2
err2

コプロセスを使用すると、問題がある場合は何度もTを呼び出す必要がなくなります。

$ coproc tee -a log
[1] 26417
$ echo out1 >> log
$ echo err1 >&"${COPROC[1]}"
$ echo out2 >> log
$ echo err2 >&"${COPROC[1]}"
$ cat log
out1
err1
out2
err2

どんなエラーがあっても、コプロセスの出力パイプで待っています。何かがあるかどうかを確認するだけでよい場合は、次のようになります。

$ timeout 1 head -n1 <&"${COPROC[0]}" >/dev/null && echo yes # or something else
yes

エラーを再利用したい場合は、目的に合わせてコプロセスを変更することをお勧めします。

スクリプトとバイナリにもリダイレクトを設定できます。彼ら自身がハードワイヤードリダイレクトを持っていない限り、もちろん。従ってこれをすることができます

$ some_executable 2>&"${COPROC[1]}" >>log

そして論理は変わりません。


これはうまく機能し、簡単ですが、echoコマンドは単なる例です。インストールされているサードパーティのスクリプトやバイナリでリダイレクトを使用したいのですが、この方法で変更するのは面倒です。知りませんでした coproc、それはコードをより良くするが、上記の問題を解決するようには思われない。
TPE

@ TPE関係ありません。説明を付け加えました。
Tomasz

スクリプトやバイナリにもリダイレクトを設定できます。実行可能ファイルが特定の順序でstdoutとstderrの両方に書き込まれたとしても、うまくいかないと思います。
TPE

@TPE試してみましたか?
Tomasz

はい、echoコマンドを .sh また、このような出力を持つ単純なCプログラムを試してみました。 write(2, "err1\n", 5);
TPE
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.