回答:
exit #
は、スクリプトではなく関数内にコマンドを配置している可能性があります。(その場合はreturn #
代わりに使用してください。)
exit 0
、スクリプトを終了して0を返します(成功したこのスクリプトの結果を使用する可能性のある他のスクリプトに伝える)
set -eを使用します
#!/bin/bash
set -e
/bin/command-that-fails
/bin/command-that-fails2
スクリプトは、失敗した最初の行の後で終了します(ゼロ以外の終了コードを返します)。この場合、command-that-fails2は実行されません。
すべてのコマンドの戻りステータスを確認すると、スクリプトは次のようになります。
#!/bin/bash
# I'm assuming you're using make
cd /project-dir
make
if [[ $? -ne 0 ]] ; then
exit 1
fi
cd /project-dir2
make
if [[ $? -ne 0 ]] ; then
exit 1
fi
セット-e、それは次のようになります。
#!/bin/bash
set -e
cd /project-dir
make
cd /project-dir2
make
コマンドが失敗すると、スクリプト全体が失敗し、$?で確認できる終了ステータスが返されます。。スクリプトが非常に長い場合、または多くのものを作成している場合、どこにでもリターンステータスチェックを追加すると、スクリプトがかなり醜くなります。
set -e
あなたはまだ可能にするいくつかのスクリプトを停止せずにエラーが発生したコマンドの終了を:command 2>&1 || echo $?
。
set -e
パイプラインまたはコマンド構造がゼロ以外の値を返す場合、スクリプトは中止されます。たとえばfoo || bar
、両方がゼロ以外の値foo
をbar
返す場合のみ失敗します。通常、適切に記述されたbashスクリプトはset -e
、最初に追加した場合に機能し、追加は自動健全性チェックとして機能します。問題が発生した場合はスクリプトを中止します。
set -o pipefail
オプションを設定することにより、コマンドのいずれかが失敗した場合にも失敗する可能性があります。
set -e
はちょうどでしょうmake || exit $?
。
SysOpsの人がかつて私に3本指の爪のテクニックを教えました:
yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "cannot $*"; }
これらの関数は* NIX OSであり、シェルのフレーバーに対応しています。それらをスクリプト(bashなど)の最初に置きtry()
、ステートメントとコードをオンにします。
(飛行羊のコメントに基づく )。
yell
:スクリプト名とすべての引数をstderr
:
$0
スクリプトへのパスです。$*
すべて引数です。 >&2
>
stdoutを&pipeにリダイレクト2
することを意味します。パイプ1
stdout
自体になります。die
と同じですがyell
、「失敗」を意味する0以外の終了ステータスで終了します。try
||
(boolean OR
)を使用します。これは、左側が失敗した場合にのみ右側を評価します。
$@
再びすべての引数ですが、異なります。die() { yell "$1"; exit $2; }
、でメッセージを渡し、コードを終了できるようにしましたdie "divide by zero" 115
。
yell
とdie
。しかし、try
それほどではありません。使用例を教えてください。
でスクリプトを呼び出す場合は、スクリプトの終了ステータスをどこでsource
使用するreturn <x>
か<x>
を指定できます(エラーまたはfalseにはゼロ以外の値を使用します)。しかし、実行可能スクリプトを呼び出すと(つまり、ファイル名で直接)、returnステートメントは不平を表示します(エラーメッセージ「return:関数またはソーススクリプトからのみ「戻る」ことができます)。
場合はexit <x>
代わりに使用されているスクリプトがで呼び出されたとき、source
それはスクリプトを開始したシェルを終了になりますが、期待通りに実行可能スクリプトは、ちょうど、終了します。
同じスクリプトでどちらの場合も処理するには、次を使用できます
return <x> 2> /dev/null || exit <x>
これは、適切な呼び出しを処理します。これは、スクリプトのトップレベルでこのステートメントを使用することを前提としています。関数内からスクリプトを直接終了しないことをお勧めします。
注意: <x>
は単なる数値と見なされます。
エラーを処理するために、run()という関数を含めることがよくあります。実行するすべての呼び出しはこの関数に渡されるので、エラーが発生するとスクリプト全体が終了します。これがset -eソリューションよりも優れている点は、行が失敗してもスクリプトが警告なしに終了せず、問題が何であるかを通知できることです。次の例では、スクリプトがfalseの呼び出しで終了するため、3行目は実行されません。
function run() {
cmd_output=$(eval $1)
return_value=$?
if [ $return_value != 0 ]; then
echo "Command $1 failed"
exit -1
else
echo "output: $cmd_output"
echo "Command succeeded."
fi
return $return_value
}
run "date"
run "false"
run "date"
set -e option
。次に、コマンドには引数が付いているため、次のようなbashの問題を回避するために一重引用符を使用しましたrunTry 'mysqldump $DB_PASS --user="$DB_USER" --host="$BV_DB_HOST" --triggers --routines --events --single-transaction --verbose $DB_SCHEMA $tables -r $BACKUP_DIR/$tables$BACKUP_FILE_NAME'
。注関数の名前をrunTryに変更しました。
eval
任意の入力を受け入れると潜在的に危険ですが、それ以外の場合はかなり見栄えがします。
構成の代わりにif
、短絡評価を活用できます。
#!/usr/bin/env bash
echo $[1+1]
echo $[2/0] # division by 0 but execution of script proceeds
echo $[3+1]
(echo $[4/0]) || exit $? # script halted with code 1 returned from `echo`
echo $[5+1]
代替演算子の優先度のために必要な括弧のペアに注意してください。$?
最近呼び出されたコマンドの終了コードに設定される特別な変数です。
command -that --fails || exit $?
かっこなしで機能する場合、それecho $[4/0]
が必要になるのはなぜですか?
echo $[4/0] || exit $?
)bashが実行されることはありませんecho
、ましてやオベイ||
。
同じ質問がありますが、重複するため質問できません。
スクリプトがもう少し複雑な場合、exitを使用して受け入れられた回答は機能しません。バックグラウンドプロセスを使用して状態を確認する場合、exitはサブシェルで実行されるため、そのプロセスのみを終了します。スクリプトを強制終了するには、明示的に強制終了する必要があります(少なくとも、それが私が知っている唯一の方法です)。
これを行う方法についての簡単なスクリプトは次のとおりです。
#!/bin/bash
boom() {
while true; do sleep 1.2; echo boom; done
}
f() {
echo Hello
N=0
while
((N++ <10))
do
sleep 1
echo $N
# ((N > 5)) && exit 4 # does not work
((N > 5)) && { kill -9 $$; exit 5; } # works
done
}
boom &
f &
while true; do sleep 0.5; echo beep; done
これはより良い答えですが、まだ不完全ですa私はブームの部分を取り除く方法を本当に知りません。
1
一貫して使用できます。スクリプトが別のスクリプトによって実行されることを意図している場合、特定の意味を持つ独自のステータスコードのセットを定義することができます。たとえば、1
==テストが失敗した、2
==コンパイルが失敗した。スクリプトが他のものの一部である場合、そこで使用されているプラクティスに一致するようにコードを調整する必要がある場合があります。たとえば、automakeによって実行されたテストスイートの一部である場合、コード77
は、スキップされたテストをマークするために使用されます。