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