Shell / Bashのstderrに印刷された項目の簡単なテストはありますか?

Shell / Bashのstderrに印刷された項目の簡単なテストはありますか?

継続的な統合のために、シェルスクリプトからコマンドを呼び出したいと思います。終了状態 0 は成功を示し、そうでなければ失敗します。複数のコマンドを実行し、いずれかのコマンドでエラーが発生した場合に失敗するようにラッパースクリプトを作成しています。

ただし、コマンドの1つ(サードパーティ製ソフトウェア)は、失敗時に「事実上」シャットダウンステータス!= 1に従わないことに注意してください。ただし、失敗が発生した場合は、stderrにエラーを印刷します。

現在のラッパースクリプトは、両方が正常に動作している場合、スイッチによってmycommandシャットダウン状態が原因で失敗します。 = 0:other-command-e

#!/bin/bash -ex
mycommand --some-argument /some/path/to/file
other-command --other-argument /some/other/file

stderrに印刷された項目があるかどうかを確認できます(メインスクリプトの失敗の原因)。私が試したことは次のとおりです。

  1. stderr 出力がファイルにリダイレクトされ、ファイルの内容が検査されます。
    一時ファイルの生成を避けたい。
  2. たとえば、stderrをサブシェルstdinにリダイレクトします。

    mycommand 2> >(if grep .; then echo NOK; else echo OK; fi)
    

    これはうまくいくようですが、ここではメインシェルのシャットダウンを制御できません。つまり、exit 1メインプログラムを終了しません。さらに、結果を伝播するためにサブシェルの外側の変数を制御することはできません。本当に名前付きパイプのようなものを作るべきですか?

  3. 追加のファイル記述子を設定します。この回答
    私が見るにはあまりエレガントに見えませんね。

いくつかの「要件」:

  • stdoutの通常の出力(やはり出力)では失敗しないでください。
  • 標準出力に他の有用な出力を維持したいと思います。
  • 私は現在stderrに印刷されているすべての出力を維持したいと思います(stdoutかもしれませんが、隠してはいけません)。

したがって、ラッパーのように動作し、不正な状態でのみ終了し、印刷物を保持する必要があります。

stderrで何でも確認できるもう少しエレガントな機能があったらと思います。侮辱は許可されています。

ベストアンサー1

次のようにできます(POSIXly)。

if { cmd 2>&1 >&3 3>&- | grep '^' >&2; } 3>&1; then
  echo there was some output on stderr
fi

または、元の終了状態を維持します(ゼロ以外の場合)。

fail_if_stderr() (
  rc=$({
    ("$@" 2>&1 >&3 3>&- 4>&-; echo "$?" >&4) |
    grep '^' >&2 3>&- 4>&-
  } 4>&1)
  err=$?
  [ "$rc" -eq 0 ] || exit "$rc"
  [ "$err" -ne 0 ] || exit 125
) 3>&1

125コマンドがゼロ終了ステータスを返しますが、いくつかのエラー出力を生成する状況には終了コードを使用します。

次のように使用されます。

fail_if_stderr cmd its args || echo "Failed with $?"

おすすめ記事