コマンドが成功すると、bashスクリプトを終了します。

コマンドが成功すると、bashスクリプトを終了します。

通常、次のような単純な煙テストスクリプトがあります。

set -e

run-command
run-other-command

echo ok

これは、コマンドが成功すると予想されるときに完全に機能します。失敗した場合、set -eスクリプトはゼロ以外の終了コードで早く終了します。

しかし、時にはコマンドが失敗することを期待し、スクリプトが別の方法で終了することを望んでいます(たとえば、コマンドがコード0で終了した場合など)。私は次のように書くことができると思いました。

set -e
run-command-that-succeeds
! run-command-that-fails

ただし、これは終了コードを無視します。 Bashのマニュアルページでは、次のように説明しますset -e

コマンドの戻り値が!で否定されると、シェルは終了しません[...]

有効な選択肢は次のとおりです。

set -e
! run-command-that-fails
[[ $? -eq 0 ]]

そして

set -e
if run-command-that-fails; then
  exit 1
fi

これが最良のオプションですか、それともコマンドが成功したときに終了するよりも寛容な選択肢がありますか?

答え1

私のテストによると、これは(! run-command-that-fails)解決策です。run-command-that-failsサブシェルで実行されます。

run-command-that-fails何らかの理由でプライマリシェルで実行する必要がある場合は、別のソリューションが必要です。私はそれだった{ ! run-command-that-fails; }ことに気づいた。いいえ一方通行。

答え2

set -e完全にあきらめて、次のようなものを使用すると簡単になります。

should-fail    && exit 1
should-succeed || exit 1

上記のコードではshould-fail失敗が予想され、失敗するとスクリプトはゼロ以外の終了コードで終了します。

2番目の操作は成功すると予想されますが、そうでなければスクリプトは終了します。

または AND-OR リストを一貫して使用するには

! should-fail  || exit 1
should-succeed || exit 1 

または

should-fail      && exit 1
! should-succeed && exit 1

失敗した場合に単純なもの以上が必要な場合は、exit次のようにします。

if should-fail; then
    # handle failure in test
    exit 1
fi

if ! should-succeed; then
    # handle failure in test
    exit 1
fi

ご存知のように、アクティブset -e状態ではコマンドの終了状態が反転してもシェルは終了しません!。これは POSIX 要件です。次の内容は、以下から取得したものです。特別な組み込みユーティリティのPOSIX仕様set、私は強調する:

、、予約語の後に-eある複合リストを実行する場合は、この設定を無視する必要があります。whileuntilifelif!予約語で始まるパイプ、またはリストの最後のコマンドを除くすべてのコマンドをAND-ORします。

関連情報