終了ステータスよる条件分岐

Bashにおいて、前に実行されたコマンドの終了ステータスは「$?」で取得することができます。

$ echo Hello
Hello
$ echo $?
0

終了ステータスは各コマンドによって定義されており、0から255までの値をとることができます。慣習的に、コマンドが正常終了した場合は0が返され、異常終了の場合はその理由に応じて0以外の数字が返されます。上記の例であれば、echoコマンドで正しくHelloが出力され、正常に終了したため、終了ステータスは0となります。

シェルスクリプトにおいては、この終了ステータスを元に条件分岐をさせる場合があります。例えば、あるコマンドを実行して、それが正常終了しなかった場合にエラーメッセージを画面に表示させるには、以下のように行います。

#!/bin/bash

command

if [ $? -ne 0 ]; then
    echo "Error occurred while executing 'command'"
fi

複数の終了ステータスに応じて条件分岐させる場合には注意が必要です。例えば、以下のプログラムは正しく動きません。

#!/bin/bash

command

if [ $? -eq 0 ]; then
    echo "Success"
elif [ $? -eq 1 ]; then
    echo "Failure: Exit status = 1"
elif [ $? -eq 2 ]; then
    echo "Failure: Exit status = 2"
else
    echo "Failure: Others"
fi

commandが正常終了した場合は、「Success」と正しく出力されますが、異常終了の場合は、終了ステータスに関わらず「Failure: Exit status = 1」が出力されてしまいます。これは、最初のif文の「[ $? -eq 0 ]」によって、$?に1が上書きされてしまうためです。「[]」は「test」コマンドの略式であり、引数の条件式が真の場合は0を、偽の場合は1の終了ステータスを返すため、今回のケースでは、$?が0以外の場合は常に1を返すことになります。この問題を避ける方法は単純で、以下のように、command終了後すぐに$?を別の変数に代入し、条件分岐にはその変数を利用するようにします。

#!/bin/bash

command
rc=$?

if [ $rc -eq 0 ]; then
    echo "Success"
elif [ $rc -eq 1 ]; then
    echo "Failure: Exit status = 1"
elif [ $rc -eq 2 ]; then
    echo "Failure: Exit status = 2"
else
    echo "Failure: Others"
fi

 

Top