終了ステータスを$?とif文で比較してはいけない

プロセスの終了ステータスを$?で取得し、if文で判断するshellスクリプトは書いてはいけない。if文を使うということは、条件文としてtestコマンドを使うことになり、ifとelif(の中のtestコマンド)が実行されるたびに、終了ステータス$?が変わってしまう。

以下にサンプルコードを書く。

実行してみると、次のようにif文が正しくマッチしない。

return_valを実行した結果、$?は2になる。しかし、初めのif [ $? = 3 ]が条件にマッチしないため、testコマンド([コマンド)の終了ステータスである1が$?を上書きしてしまう。その結果、つぎのelif [ $? = 2 ]が本来マッチしてほしいはずなのにマッチしなくなってしまう。
運よくif文の初めの条件文でマッチした場合は正しく判定できるが、if文内のコマンド実行部分ではすでに$?が0で上書きされてしまっているため、$?を使用できない。

対策は簡単で、$?を変数に格納してあげればいい。

実行してみると、正しいif文にマッチする。ただし$?はif文内では先述の通りtestコマンドの結果で上書きされているため使用できない。

if test $? = 3と書いていれば、$?testコマンドで上書きされることに気づきやすい。しかし、今回のように[コマンドで書いてしまうと、実際にはtestコマンドで書いたことと同じ扱いなのに、if文の構文のように見えてしまう。コマンドを実行したという意識が希薄になって$?が上書きされることにも気づきにくくなるので、注意が必要。

-Linux