シェルスクリプトの一部が失敗した場合に終了するにはどうすればよいですか?

一部が失敗した場合に終了するシェルスクリプトを作成するにはどうすればよいですか?たとえば、次のコードスニペットが失敗した場合、スクリプトは終了する必要があります。

n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3 

回答

1つのアプローチは、スクリプトの先頭にset -eを追加することです。つまり、(help setから):

 -e Exit immediately if a command exits with a non-zero status. 

したがって、コマンドのいずれかが失敗すると、スクリプトは終了します。

または、考えられる障害ポイントに明示的なexitステートメントを追加できます。

command || exit 1 

コメント

  • 私(および bash wiki )は、適切なエラー処理について考えを入れたいと考えています。 (設計IMOによって壊れた)set -e機能を使用するのではなく。ただし、ここでは実際には適用されません'。 OPは、コマンドの実行に5回失敗した後、スクリプトを終了しようとしています。
  • @St é phaneChazelas勝ちました' 'が壊れているかどうかについてあなたと議論します、私は'あなたが'正しい。ただし、OPは"一部が失敗した場合に終了するシェルスクリプトを作成するにはどうすればよいですか?"、何が原因ですか? ' 5回失敗した後に終了することについて考えますか?
  • '他の方法を考えることができないため質問は解釈できます。
  • @St é phaneChazelasあなたは正しいかもしれません。私はそれを文字通りに解釈しました。スクリプトの一部が失敗した場合、スクリプト全体をどのように終了できるのでしょうか。そして、set -eが私が知っている唯一の方法です。
  • そのスクリプトスニペットでは、set -esleepbreakは特別な組み込みであるため、ほとんどのシェルで失敗するとスクリプトが終了します。ifまたは&&の左側は、set -en=...

が読み取り専用の場合、

が失敗する可能性がありますが、set -eがないとスクリプトが終了するため、解釈はほとんどありそうにありません。質問の表現が不十分であることに同意します。

回答

キーワードを使用して、任意の場所でスクリプトを終了できますexit。スクリプトが失敗したことやスクリプトがどのように失敗したかを他のプログラムに示すために、終了コードを指定することもできます。 exit 1またはexit 2など(慣例により、終了コード0は成功を示し、0より大きいものは失敗を示します。ただし、慣例により、 、127を超える終了コードは、異常終了(信号などによる)用に予約されています。

障害時に終了する一般的な構造は

if [ failure condition ]; then exit n fi 

適切なfailure conditionおよびnを使用します。ただし、特定のシナリオでは、進行が異なる場合があります。ここで、あなたのケースでは、gksuの5つの呼び出しのいずれかが失敗した場合、終了することを意味するというあなたの質問を解釈します。 1つの方法は、次のような関数を使用することです

function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 } 

次に、try_commandによってループを呼び出します。

質問に対処する方法には、(より)高度な方法または洗練された方法があります。ただし、上記のソリューションは、たとえばステファンのソリューションよりも初心者が利用しやすいものです。

回答

attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done 

exitは、サブシェルで呼び出されない限り、スクリプトを終了します。スクリプトのその部分がサブシェルにある場合、たとえば、(...)または$(...)内、またはパイプラインの一部であるため、その後、そのサブシェルのみを終了します。

その場合、サブシェルに加えてスクリプトを終了する場合は、「そのサブシェルが終了したら、exitを呼び出す必要があります。

たとえば、ここでは2つのネストされたレベルのサブシェルがあります。

( life=hard output=$( echo blah [ "$life" = easy ] || exit 1 # exit subshell echo blih not run ) || exit # if the subshell exits with a non-zero exit status, # exit as well with the same exit status echo not run either ) || exit # if the subshell exits with a non-zero exit status, # exit as well with the same exit status 

サブシェルがパイプラインの一部である場合、扱いが難しくなる可能性があります。 bashには、zshのivid = “と同様に、特別な$PIPESTATUS配列があります。 cbe7c9bdfe “>

ここで役立つもの:

{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi 

回答

Trapは、シグナルを受信するとアクションを実行します。

trap "echo EXIT; exit" 0 trap "echo HUP; exit" 1 trap "echo CTL-C; exit" 2 trap "echo QUIT; exit" 3 trap "echo ERR; exit" ERR n=0 until [ $n -ge 5 ] do n=$[$n+1] echo $n sleep 3 done 

これを実行して、通常どおり終了します。シグナル0でトラップします。

EXIT 

もう一度実行し、^ Cで中断します。信号2と信号0の両方をトラップします。

CTL-C EXIT 

ゼロ以外の終了ステータスはERRでトラップされます

ERR EXIT 

回答

pass_to_functio() { echo "command exited with status $1" } ( exec <Any Command > & child_pid=$! wait $child_pid pass_to_function $? )& 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です