条件が失敗したときにbashスクリプトを停止する方法は?


11

ここでは、||&&を1行で使用してコマンドの実行を連結することを示しています。bashスクリプトでapt-getエラーを確認するにはどうすればよいですか?

特定の条件が失敗した場合、スクリプトの実行を停止しようとしていますが、

例えば

false || echo "Obvious error because its false on left" && exit

ここでObvious error because its false on the leftは、コンソールを表示して終了します。これは、私が望んでいたものです。

true || echo "This shouldn't print" && exit

ここでは、エコー出力はありませんが、exitコマンドも実行されます。つまり、コンソールが閉じられexitます。右側のエコーコマンドが実行されなかったため、コマンドは実行されませんか?または、デフォルトでは、&&演算子の左側のステートメントは偽と見なされますか?

編集:私は前にそれを言及する必要がありました、私の目的はエラーをエコーし​​、明確でない場合終了することでした。&&および||を使用して条件をグループ化するときにエラーをキャッチするという特定のケースについては、@ bodhi.zazenの回答が問題を解決します。

@takatakatekの回答により、フロー制御がより明確になり、bashガイドリンクが優れています

@muruの回答には、より堅牢な方法であるperlとtrapを使用する代替手段でカスタムエラーメッセージをスローする場合、set -eを使用しない理由の良い説明があり、2番目のbashスクリプト以降でそれを使用していることがわかります!


私の知る限り、スクリプトが完了すると終了します。
パンサー

回答:


10

あなたはおそらく(steeldriverが指摘したように)

true || { echo "This shouldn't print" && exit; }

それ以外の場合、スクリプトは一度に1つの条件を読み取ります

aまたはbから終了

または(bおよびexit)が必要だと思いますか?


4
実際には、使用する必要あります{ ... ; }(@steeldriver推奨)、またはexitサブシェルを終了するだけで、親シェルはスクリプトの実行を継続します。
ゴードンデイヴィソン

14

問題は、|| および&&は、条件が失敗したときにコマンドチェーンの後続のスタンザを1つだけスキップします。完全なブロック構造を書き出す場合、完全に理にかなっています。あなたが書いたものはこれになります:

if ! true ; then
   echo "This shouldn't print"
else
   exit
fi

あなたが欲しいのはこれです:

if ! true ; then
   echo "This shouldn't print"
   exit
fi

Bashのショートカット条件付き演算子を使用している場合、それらを混在させないようにすることをお勧めします。ロジックは、作成中に理解するのがはるかに簡単であり、読者はあなたの良いスタイルに感謝します。


2
はい、私の意見では、これはbashのコンディショニングがどのように書かれるべきかということです
-derHugo

@takatakatekこれにより、私の場合に失敗する理由がより明確になります。このロジックは明確ですが、&&と||を使用して条件をグループ化する理由ではないことに同意します。条件文を使用してそれらを表現することを避けることですか?
コソル

@kosolはい、&&および|| 前のコマンドの終了ステータスをテストし、実行(&&の場合)またはスキップ(||の場合)する単一のコマンド(またはコマンドグループ)を指定します。これらは非常に単純な場合に役立ちますが、完全に表現されたif ... then ... elif ... else ... fiブロックを置き換えることはできません。Bashには、より洗練された言語で見られる真のブール型がないことに気付いていないのではないかと思います。コマンドの終了ステータスが0(ゼロ)の場合、Bashはそれをtrue / successとして扱います。終了ステータスがゼロ以外の場合、Bashはそれをfalse / failureとして扱います。
takatakatek

7

エラーで失敗する最も簡単な方法は、bashの-eオプションを使用することです(set -eまたは/bin/bash -eシェバンで)。ただし、これではカスタムエラーメッセージを簡単に送信できません。よりシンプルにするいくつかのイディオムがあります:

die アラペル

Perlには、stderrにメッセージを出力して例外を発生させる非常に便利なdieコマンドがあり、通常はスクリプトが終了します。これをエミュレートできます:

die () {
  ret=$?
  print "%s\n" "$@" >&2
  exit "$ret"
}

false || die "Obvious error because its false on left"
true || die "This shouldn't print"

trap ERR

このtrap <command>コマンドを使用して、信号を受信したとき、スクリプトを終了するとき(trap ... EXIT)、またはコマンドがエラーを返すとき()にコマンドを実行できますtrap ... ERR。のようなもの:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR

次に:

ERR_MSG="Obvious error because its false here"
false
ERR_MSG="This shouldn't print"
true

どちらの場合でもexit 1、スクリプトが失敗したことを示すために、少なくともを使用することをお勧めます。プレーンexitは、前のコマンドの終了ステータスを使用します。これらの場合、通常は成功するechoor printfコマンドです。ここで行ったように、失敗したコマンドの終了ステータスを保存しておくと便利です。


6

スクリプトを開始して少し試してみることができます

#!/bin/bash -e

-eは、何かがfalseを返したときにスクリプトが終了することを保証します。これにより、特定の障害を回避できますsomething || true

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.