私はシェルスクリプトの初心者です。コマンドが失敗した場合、メッセージを出力してスクリプトを終了します。私はもう試した:
my_command && (echo 'my_command failed; exit)
しかし、それは機能しません。スクリプトのこの行に続く命令を実行し続けます。 Ubuntuとbashを使用しています。
試してください:
my_command || { echo 'my_command failed' ; exit 1; }
4つの変更:
&&
を||
に変更します{ }
の代わりに( )
を使用しますexit
の後に;
を導入し、{
の後、}
の前のスペースメッセージが出力され、コマンドが失敗した(ゼロ以外の値で終了する)場合にのみ終了するため、||
ではなく&&
が必要です。
cmd1 && cmd2
cmd2
が成功するとcmd1
が実行されます(終了値0
)。どこに
cmd1 || cmd2
cmd2
が失敗したときにcmd1
を実行します(終了値がゼロ以外)。
( )
を使用すると、内部のコマンドがsub-Shellで実行され、そこからexit
を呼び出すと、サブルーチンが終了します-元のシェルではなくシェル。したがって、元のシェルで実行が続行されます。
これを克服するには、{ }
を使用します
最後の2つの変更は、bashに必要です。
他の答えは直接の質問をうまくカバーしていますが、set -e
の使用にも興味があるかもしれません。これにより、失敗したコマンド(if
テストなどの特定のコンテキスト以外)は、スクリプトを中止します。特定のスクリプトでは、非常に便利です。
スクリプト内のすべてのコマンドに対してその動作が必要な場合は、追加するだけです
set -e
set -o pipefail
スクリプトの冒頭。このオプションのペアは、コマンドがゼロ以外の終了コードで戻るたびに終了するようにbashインタープリターに指示します。
ただし、終了メッセージを出力することはできません。
また、各コマンドの終了ステータスはシェル変数$?に保存されます。これは、コマンドの実行後すぐに確認できます。ゼロ以外のステータスは失敗を示します。
my_command
if [ $? -eq 0 ]
then
echo "it worked"
else
echo "it failed"
fi
次のイディオムをハックしました:
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 ];...
行。 (もちろん、必要に応じてそのエラーメッセージを編集できます。)
my_command
が標準的に設計されている場合、ieは成功すると0を返し、&&
は必要なものとまったく逆になります。 ||
が必要です。
また、(
はbashでは私には正しくないと思われますが、現在の場所から試すことはできません。教えてください。
my_command || {
echo 'my_command failed' ;
exit 1;
}
終了エラーステータスを保持したい場合は、1行に1つのコマンドを含む読み取り可能なファイルを使用することもできます。
my_command1 || exit $?
my_command2 || exit $?
ただし、これは追加のエラーメッセージを出力しません。ただし、場合によっては、失敗したコマンドによってエラーが出力されます。
trap
Shellビルトインは、シグナルのキャッチ、および失敗したコマンド実行(つまり、ゼロ以外の戻りステータス)を含む他の有用な条件を許可します。したがって、すべてのコマンドのリターンステータスを明示的にテストする必要がない場合は、trap "your Shell code" ERR
と言うことができ、コマンドがゼロ以外のステータスを返すたびにシェルコードが実行されます。例えば:
trap "echo script failed; exit 1" ERR
失敗したコマンドをキャッチする他の場合と同様に、パイプラインには特別な処理が必要です。上記はfalse | true
をキャッチしません。
次の関数は、コマンドが失敗した場合にのみエラーをエコーします。
silently () {
label="${1}"
command="${2}"
error=$(eval "${command}" 2>&1 >"/dev/null")
if [ ${?} -ne 0 ]; then
echo "${label}: ${error}" >&2
exit 1
fi
}