stderrが存在する場合は、通知を送信するために通知本文でstderrを使用します。

stderrが存在する場合は、通知を送信するために通知本文でstderrを使用します。

次のようなコマンドがあるとしましょう。

foo() {
    echo a
    echo b >&2
    echo c
    echo d >&2
}

次のコマンドを使用して端末でstdoutを処理していますが、通知を介してエラーが送信されます。

foo 1> >(cat) 2> >(ifne notify-send "Error")

b d私が経験している問題は、stderr(この場合)を通知送信の本文として処理したいということです。

私は試した:

foo 1> >(cat) 2> >(ifne notify-send "Error" "$(cat)")
foo 1> >(cat) 2> >(ifne notify-send "Error" "$(</dev/stdin)")

何も動作しません。ここで解決策は何ですか?

答え1

試してみると、"$(cat)"ほとんどやってきましたが、それに従うのではなくcatで読む必要があります。ifneifne

ifne notify-send "Error" "$(cat)"の場合、cat同じストリームで読み取りが行われますが、ifne同時には行われません。コードのこの部分を処理するシェルはifne終了後にのみ実行できます。なぜなら、それ以降に拡張する必要がある項目、つまりどの引数を取得するのかをcat知ることができるからです。終了後、ストリームはすべて消費され、対応する入力は空です。$(cat)finecatifne

以下を使用してcat読み取りを実行する方法は次のとおりですifne

foo 2> >(ifne sh -c 'exec notify-send "Error" "$(cat)"')

(何が目的なのかよくわかりません1> >(cat)。スキップしました。)

これは、ifne(条件付きで)実行中のすべての項目の標準入力に入力を渡します。ただし、実行されるすべての項目shsh標準入力を共有します。catで効果的に読みますifne。試みと同様に、終了した後にexec notify-sendのみcat実行できるため、notify-send標準入力から読み取ろうとしても、catすべてが最初に消費されます。

データが多すぎると、この方法は失敗する可能性がありますcat。パラメータリストは任意に長くすることはできません。そしてcat終了後にのみ終了するので、fooこの方法は終了時にうまく機能し、foostderrにあまりにも多くのメッセージを生成しません。

長期使用の代わりに使用することxargsをお勧めします。$(cat)foo時々エラー行が生成されます。これの例は次のとおりですfoo

foo() {
    echo a
    echo b >&2
    sleep 10
    echo c
    echo d >&2
    sleep 20
}

この場合、上記の解決策が必ずしも良いわけではありませんfoo(一度試してください)。それとはxargs異なります。foo無制限に実行される可能性があり、エラーがある場合はすぐに通知を受け取ります(一度に1行ずつ)。 ()をxargs支持するならば、それは必要ありません。以下はコマンドの例です。--no-run-if-empty-rifnexargs

foo 2> >(xargs -r -I{} notify-send "Error" {})

(これはxargsまだ引用符とバックスラッシュを解釈します。)

関連情報