私は複数のコマンドを実行する必要があるシェルスクリプトを作成していますが、各コマンドは以前のすべてのコマンドによって異なります。コマンドが失敗すると、スクリプト全体が失敗し、終了関数を呼び出します。各コマンドの終了コードを確認できますが、有効にするモードがあるかどうか、またはbashにこの操作を自動的に実行させる方法があるかどうかを知りたいです。
たとえば、次のコマンドを使用します。
cd foo || myfunc
rm a || myfunc
cd bar || myfunc
rm b || myfunc
このコマンドを実行する前にコマンドのいずれかが失敗した場合は、myfuncを呼び出して次のようにきちんと作成できるようにシェルにシグナルを送信する方法はありますか?
cd foo
rm a
cd bar
rm b
答え1
バッシュが使えますトラップエラーコマンドがゼロより大きい状態を返す場合は、スクリプトを終了し、終了時に関数を実行します。
それは次のとおりです。
myfunc() {
echo 'Error raised. Exiting!'
}
trap 'myfunc' ERR
# file does not exist, causing error
ls asd
echo 123
気づくスラムトラップ ERR
暗黙的なset -o errexit
orset -e
と は POSIX ではありません。
失敗したコマンドが、またはキーワードの直後のコマンドリストの一部であるか、予約語の後のテストの一部であるか、リストで実行されたコマンドの一部である、またはコマンドの戻り状態が反転を使用している場合、ERR
トラップは実行されません。until
while
if
elif
&&
||
!
答え2
許容される答えの(おそらく)より単純なバリエーションです。
set -e
コマンドが失敗し、リストの実行が中断されるようにするために使用されます。- コマンドをリストするだけです。
if
-then
- 文を使用してelse
エラー処理コマンドを実行します。最後の部分が少しトリッキーですね。より:
セット もし コマンド1 #例えば、cd foo コマンド2 # たとえば、rm a コマンド3 #例えばCDバー コマンド4 # たとえば、rm b それから セット+e 成功時に実行するコマンド(存在する場合) その他 セット+e 私の機能 失敗した場合に実行する追加コマンド(存在する場合) フィリピン諸島
難しい部分は、コマンドを入力することです。
入力するそのif
部分部分または部分の代わりに- if
-then
を使用してください。それを覚えてelse
then
else
if
お問い合わせ構文はい
もし リスト;それから リスト;[イルライフ リスト;それから リスト;] ... [その他 リスト;]ペイ ↑↑↑↑
set -e
()が失敗した場合は、()実行を続行しないことをシェルに伝えます。シェルスクリプトの最も外側のコマンドでこれが発生すると、シェルは終了します。しかし...以降は(複合)リストで、その後にはcmd1
cd foo
cmd2
rm a
cmd1
cmd2
cmd3
cmd4
if
、これら4つのコマンドのいずれかが失敗すると、リスト全体が失敗し、対応する句がelse
実行されます。 4つのコマンドがすべて成功すると、then
この句が実行されます。
e
どちらの場合も、最初にすべきことは、次の手順を実行してオプションを無効にする(オフにする)ことですset +e
。そうしないと、コマンドが失敗するとmyfunc
スクリプトが水から飛び出す可能性があります。
set -e
はいPOSIX仕様で指定および説明。
答え3
約束を守ってください」各コマンドは、前のすべてのコマンドによって異なります。コマンドが失敗すると、スクリプト全体が失敗します。「文字通りエラーを処理するために特別な機能が必要だとは思わない。
あなたがしなければならないのは、&&
演算子と||
演算子を使用してコマンドを連結することだけで、それがまさにあなたが書くことです。
たとえば、次のような場合、チェーンが壊れて「何かが間違っています」と印刷されます。どの前のコマンドが破損しています(Bashは左から右に読みます)。
cd foo && rm a && cd bar && rm b || echo "something went wrong"
実際の例(実際のデモのためにdir foo、file a、dir bar、およびfile bを作成しました):
gv@debian:/home/gv/Desktop/PythonTests$ cd foo && rm a && cd bar && rm bb || echo "something is wrong"
rm: cannot remove 'bb': No such file or directory
something is wrong #mind the error in the last command
gv@debian:/home/gv/Desktop/PythonTests$ cd foo && rm aa && cd bar && rm b || echo "something is wrong"
rm: cannot remove 'aa': No such file or directory
something is wrong #mind the error in second command in the row
最後に、すべてのコマンドが正常に実行されると(終了コード0)、スクリプトは引き続き実行されます。
gv@debian:/home/gv/Desktop/PythonTests$ cd foo && rm a && cd bar && rm b || echo "something is wrong"
gv@debian:/home/gv/Desktop/PythonTests/foo/bar$
# mind that the error message is not printed since all commands were successful.
&& を使用すると、前のコマンドがコード 0 で終了すると、次のコマンドが実行されます。これは bash の成功を意味することを覚えておくことが重要です。
チェーンのコマンドの1つが間違っている場合は、command/script/||次のすべてのコマンドが実行されます。
記録のために中断されたコマンドに従って他の操作を実行する必要がある場合は、以前のコマンドの終了コードを報告する$?
値を監視して、既存のスクリプトを使用してこれを実行することもできます(コマンドが正常に実行されたか0を返す場合)。コマンドがそうでなければ正数です)
例:
for comm in {"cd foo","rm a","cd bbar","rm b"};do #mind the error in third command
eval $comm
if [[ $? -ne 0 ]];then
echo "something is wrong in command $comm"
break
else
echo "command $comm executed succesful"
fi
done
出力:
command cd foo executed succesfull
command rm a executed succesfull
bash: cd: bbar: No such file or directory
something is wrong in command cd bbar
ヒント:アプリでは、「bash:cd:bbar:No such file ...」というメッセージが表示されない場合があります。eval $comm 2>/dev/null