一部が失敗した場合に終了するシェルスクリプトを作成するにはどうすればよいですか?たとえば、次のコードスニペットが失敗した場合、スクリプトは終了する必要があります。
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
コメント
が読み取り専用の場合、
が失敗する可能性がありますが、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 $? )&
set -e
機能を使用するのではなく。ただし、ここでは実際には適用されません'。 OPは、コマンドの実行に5回失敗した後、スクリプトを終了しようとしています。set -e
が私が知っている唯一の方法です。set -e
はsleep
(break
は特別な組み込みであるため、ほとんどのシェルで失敗するとスクリプトが終了します。if
または&&
の左側は、set -e
、n=...