エラー時にスクリプトを終了する


141

次のifような関数を持つシェルスクリプトを作成しています。

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables
fi

...

エラーメッセージを表示した後、スクリプトの実行を終了させたい。どうすればこれを行うことができますか?

回答:


137

お探しexitですか?

これは最高のbashガイドです。 http://tldp.org/LDP/abs/html/

コンテキスト:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables 1>&2
    exit 1 # terminate and indicate error
fi

...


それらのBashリンクは素晴らしいです!BashFAQはBashRecipesとしてより適切に位置付けられます。
ピートアルビン

337

set -eスクリプトを入力した場合、スクリプトは、スクリプト内のコマンドが失敗するとすぐに(つまり、コマンドがゼロ以外のステータスを返したときに)終了します。これはあなた自身のメッセージを書くことを許しませんが、多くの場合、失敗したコマンド自身のメッセージで十分です。

このアプローチの利点は、自動化されていることです。エラーケースへの対処を忘れるリスクを冒す必要はありません。

ステータスが条件付き(if&&またはなど||)でテストされるコマンドは、スクリプトを終了しません(そうでない場合、条件は無意味になります)。失敗が問題にならない臨時のコマンドのイディオムはcommand-that-may-fail || trueです。でset -eスクリプトの一部をオフにすることもできset +eます。


3
mywiki.wooledge.org/BashFAQ/105によると、この機能には、どのコマンドのエラーコードが自動的に終了するかを決定する際に不明瞭で複雑な履歴があります。さらに、「Bashはこの「機能」の非常に滑りやすいPOSIX定義を追跡しようとするため、ルールはBashのバージョンによって異なります。」@Dennis Williamsonと、stackoverflow.com / questions / 19622198 /…の承認された回答に同意します-トラップ 'error_handler' ERRを使用します。トラップだとしても!
Bondolin

3
-xフラグを頻繁に使用する-eで、プログラムが終了する場所を追跡できます。これは、スクリプトのユーザーが開発者でもあることを意味します。
Alex

いいですが、OPは自己定義の例外からスクリプトを終了する必要があると思います。
vdegenne

42

を使用せずに、盲目的に終了する代わりにエラーを処理できるようにしたい場合は、疑似信号でset -ea trapを使用しERRます。

#!/bin/bash
f () {
    errorCode=$? # save the exit code as the first thing done in the trap function
    echo "error $errorCode"
    echo "the command executing at the time of the error was"
    echo "$BASH_COMMAND"
    echo "on line ${BASH_LINENO[0]}"
    # do some error handling, cleanup, logging, notification
    # $BASH_COMMAND contains the command that was being executed at the time of the trap
    # ${BASH_LINENO[0]} contains the line number in the script of that command
    # exit the script or return to try again, etc.
    exit $errorCode  # or use some other value or do return instead
}
trap f ERR
# do some stuff
false # returns 1 so it triggers the trap
# maybe do some other stuff

他のトラップは、通常のUnixシグナルに加えて他のBash疑似シグナルRETURNやを含む他のシグナルを処理するように設定できますDEBUG


8

これを行う方法は次のとおりです。

#!/bin/sh

abort()
{
    echo >&2 '
***************
*** ABORTED ***
***************
'
    echo "An error occurred. Exiting..." >&2
    exit 1
}

trap 'abort' 0

set -e

# Add your script below....
# If an error occurs, the abort() function will be called.
#----------------------------------------------------------
# ===> Your script goes here
# Done!
trap : 0

echo >&2 '
************
*** DONE *** 
************
'

stderrへのDONEメッセージの理由
MattBianco 14

1
これは一般的な方法であるため、スクリプト出力をstdoutにパイプして、別のプロセスが情報メッセージを途中で取得しなくても取得できるようにすることができます。
スーパーコブラ2014年

2
stderrで何かを問題の兆候として扱うことは、おそらく同じように一般的な方法です。
MattBianco 14年

1
これまでは「set -e」が常にうまく機能していましたが、今夜、Alpine Linux Dockerイメージで効果がなかった状況に遭遇しました。とても有難い。
シンセサイザ

@supercobra慣習は?どこ?
–ThorbjørnRavn Andersen、2018

-8

exit 1は、あなたが必要とすることすべてです。これ1は戻りコードなので、たとえば、1実行が成功-1したことを意味し、失敗などを意味するように変更することができます。


13
UNIXでは、成功は常に0です。これは、testor &&またはを使用するときに役立ちます||
mouviciel 2010

5
mouvicielのコメントを拡張すると、シェルスクリプトでは、0は常に成功を意味し、1から255は失敗を意味します。-1は範囲外です(多くの場合、255と同じ効果があるため、1のようなエラーが発生します)。
Gilles「SO-悪をやめる」

@ mouviciel、@ Gilles:追加情報をありがとう。私がbashを扱ってから久しぶりです。
DGH

これは戻りコードの使用法の悪い例ですが、それ以外の場合は素晴らしい答えになります。
Brad Koch

1
成功するために誤って1を推奨することに加えて、-1は不可能です(終了コードは署名されていません)。
tripleee
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.