web-dev-qa-db-ja.com

stderrをファイルにリダイレクトしますが、stderrが発生した場合にのみ作成しますか?

私は次のようなコマンドを実行しています:

parallel --spreadstdin --line-buffered 'some_command 2> `mktemp --tmpdir /tmp/stderr`' | do_something

秘訣は、parallelが多くのプロセスを作成し、それらすべてがstderrファイルを取得することです。これらのファイルのほとんどは、空であるため面白くありません。標準エラー出力が実際に発生した場合にのみ、シェルにstderrファイルを生成させるにはどうすればよいですか?

2
d33tah

私の知る限り、これは不可能です。シェルは右から左に読み取るので、2> errorが存在します。 errorファイルが作成されます。それを回避する方法はないと思います。

名前付きパイプを使用してその出力をテストするなど、いくつかの複雑なトリックを実行できる場合がありますが、それだけの価値はないと思います。代わりに、別の回答で説明されているようにinotifyを使用するか、tmpファイルを作成して、データが含まれている場合は別の場所にコピーします。

tmp=$(mktemp); command 2> "$tmp"; [ -s "$tmp" ] && cp "$tmp" /path/to/log/files
1
terdon

parallel --spreadstdin --line-buffered'some_command 2 \

mktemp --tmpdir /tmp/stderr '| do_something && if [test -s/tmp/stderr];その後;睡眠.1;そうしないと; rm/tmp/stderr

  • ファイルが存在し、TRUEのサイズがゼロより大きいかどうかをテストするためのワンライナー。 FALSEの場合は空。

それ。うまくいくことをすることです。ビットとバイトのカウントを停止し、起動時にinotifywaitトリガーを作成して、ログが空かどうかを確認し、結果をdatatableに記録して、ログオンを完全にワイプします。次に、キーワードがエラーログに表示されたときに電子メールで送信するWebインターフェイスをプログラムします。

while:
  do
    inotifywait -e create /tmp/* && \
      if [ -s /tmp/stderr ]
        then
        ##put it in a datatable
        ##remove the log
      fi
  done

iNotifyWaitは、カーネルF/Sサブシステムを監視して、追加している場合はファイルが変更されているかどうかを確認することもできます。それ以外の場合は、ソースコードを変更し、再コンパイルして、try()catch()またはエラー報告セクション(エラーコードを画面に出力する部分)を変更してエラーが作成されないようにします。

0
Tyler Maginnis

SOに関する他の質問 への答えが、マークを打つことなく質問に答えることにどれほど近づいたかは驚くべきことです。次のようにシェル関数を定義します(またはスクリプトを記述します)。

save_err()
{
    # Check that "$1" is set and either complain/abort or generate a default.
    if read -r x
    then
        { printf "%s\n" "$x"; cat; } > "$1"
    fi
}

次に、次のように使用します。

some_command 2> >( save_err $(mktemp --tmpdir /tmp/stderr) )

警告:stderr出力が1行の場合、これは失敗します改行で終わらない。これを修正するには、関数の内臓を次のように変更します

    if read -r x
    then
        { printf "%s\n" "$x"; cat; } > "$1"
    Elif [ "$x" != "" ]
    then
        printf "%s" "$x" > "$1"
    fi

ダッシュで始まるテキストや円記号を含むテキストを防ぐために、printfではなくechoを使用しました。 stderr出力の最初の行に非ASCII文字が含まれている場合、問題が発生する可能性があります。