web-dev-qa-db-ja.com

コマンドが失敗した場合に終了する方法は?

私はシェルスクリプトの初心者です。コマンドが失敗した場合、メッセージを出力してスクリプトを終了します。私はもう試した:

my_command && (echo 'my_command failed; exit)

しかし、それは機能しません。スクリプトのこの行に続く命令を実行し続けます。 Ubuntuとbashを使用しています。

176
user459246

試してください:

my_command || { echo 'my_command failed' ; exit 1; }

4つの変更:

  • &&||に変更します
  • { }の代わりに( )を使用します
  • exitの後に;を導入し、
  • {の後、}の前のスペース

メッセージが出力され、コマンドが失敗した(ゼロ以外の値で終了する)場合にのみ終了するため、||ではなく&&が必要です。

cmd1 && cmd2

cmd2が成功するとcmd1が実行されます(終了値0)。どこに

cmd1 || cmd2

cmd2が失敗したときにcmd1を実行します(終了値がゼロ以外)。

( )を使用すると、内部のコマンドがsub-Shellで実行され、そこからexitを呼び出すと、サブルーチンが終了します-元のシェルではなくシェル。したがって、元のシェルで実行が続行されます。

これを克服するには、{ }を使用します

最後の2つの変更は、bashに必要です。

334
codaddict

他の答えは直接の質問をうまくカバーしていますが、set -eの使用にも興味があるかもしれません。これにより、失敗したコマンド(ifテストなどの特定のコンテキスト以外)は、スクリプトを中止します。特定のスクリプトでは、非常に便利です。

117
Daenyth

スクリプト内のすべてのコマンドに対してその動作が必要な場合は、追加するだけです

  set -e 
  set -o pipefail

スクリプトの冒頭。このオプションのペアは、コマンドがゼロ以外の終了コードで戻るたびに終了するようにbashインタープリターに指示します。

ただし、終了メッセージを出力することはできません。

56
damienfrancois

また、各コマンドの終了ステータスはシェル変数$?に保存されます。これは、コマンドの実行後すぐに確認できます。ゼロ以外のステータスは失敗を示します。

my_command
if [ $? -eq 0 ]
then
    echo "it worked"
else
    echo "it failed"
fi
54
Alex Howansky

次のイディオムをハックしました:

echo "Generating from IDL..."
idlj -fclient -td Java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Compiling classes..."
javac *Java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Done."

各コマンドの前に有益なエコーを付け、各コマンドの後に同じものを付けます
if [ $? -ne 0 ];...行。 (もちろん、必要に応じてそのエラーメッセージを編集できます。)

11

my_commandが標準的に設計されている場合、ieは成功すると0を返し、&&は必要なものとまったく逆になります。 ||が必要です。

また、(はbashでは私には正しくないと思われますが、現在の場所から試すことはできません。教えてください。

my_command || {
    echo 'my_command failed' ;
    exit 1; 
}
10
Benoit

終了エラーステータスを保持したい場合は、1行に1つのコマンドを含む読み取り可能なファイルを使用することもできます。

my_command1 || exit $?
my_command2 || exit $?

ただし、これは追加のエラーメッセージを出力しません。ただし、場合によっては、失敗したコマンドによってエラーが出力されます。

3
alexpirine

trap Shellビルトインは、シグナルのキャッチ、および失敗したコマンド実行(つまり、ゼロ以外の戻りステータス)を含む他の有用な条件を許可します。したがって、すべてのコマンドのリターンステータスを明示的にテストする必要がない場合は、trap "your Shell code" ERRと言うことができ、コマンドがゼロ以外のステータスを返すたびにシェルコードが実行されます。例えば:

trap "echo script failed; exit 1" ERR

失敗したコマンドをキャッチする他の場合と同様に、パイプラインには特別な処理が必要です。上記はfalse | trueをキャッチしません。

3
kozel

次の関数は、コマンドが失敗した場合にのみエラーをエコーし​​ます。

silently () {
    label="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${label}: ${error}" >&2
        exit 1
    fi
}