シェルスクリプトの一部が失敗した場合に終了するシェルスクリプトを作成するにはどうすればよいですか?たとえば、次のコードスニペットが失敗した場合、スクリプトは終了します。
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
キーワード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
によってループを呼び出します。
あなたの質問に対処する方法の(もっと)高度なまたは洗練された方法があります。ただし、上記のソリューションは、たとえばStephaneのソリューションよりも初心者がアクセスしやすくなっています。
_attempt=0
until gksu command; do
attempt=$((attempt + 1))
if [ "$attempt" -gt 5 ]; then
exit 1
fi
done
_
exit
は、サブシェルで呼び出されない限り、スクリプトを終了します。スクリプトのその部分がサブシェルにある場合、たとえば、それが_(...)
_または$(...)
またはパイプラインの一部内にあるため、終了するだけですそのサブシェル =。
その場合、サブシェルに加えてscriptを終了するには、そのサブシェルの終了時に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
の_$PIPESTATUS
_配列に似た特別な_$pipestatus
_配列があり、ここで役立ちます:
_{
echo foo
exit 1
echo bar
} | wc -c
subshell_ret=${PIPESTATUS[0]}
if [ "$subshell_ret" -ne 0 ]; then
exit "$subshell_ret"
fi
_
トラップはシグナルを受信するとアクションを実行します。
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