3
1

More than 3 years have passed since last update.

Bashで終了ステータスごとに異なる処理を行いたい場合にハマった

Last updated at Posted at 2021-08-03

複数パターンの終了ステータスを返す「とあるスクリプト」を作成

終了ステータスが成功パターン(exit 0)、失敗パターンA(exit 1)、失敗パターンB(exit 2)のように3パターンにわかれる「とあるスクリプト」を作成しました。(元々のスクリプトはもっと複雑なんですが、ここでは簡略化して書いてます)

とあるスクリプト.sh
処理A || {
    # 失敗パターンA
    exit 1
}

処理B || {
    # 失敗パターンB
    exit 2
}

# 成功パターン
exit 0

「とあるスクリプト」の終了ステータスを判定して、それぞれ異なる処理を行うスクリプトを作成

「とあるスクリプト」を「呼び出す側のスクリプト」で、終了ステータスごとに異なる処理を行おうと思い、以下のような条件分岐を書きました。
元々は成功パターンと失敗パターンAの2パターンだけだったんですが、失敗パターンBが登場して3パターンとなり、以下のような分岐にしてみたという経緯があります。

呼び出す側のスクリプト.sh
bash とあるスクリプト.sh
if [ $? -eq 0 ] ; then
    echo '成功パターンの場合の処理'
elif [ $? -eq 1 ] ; then
    echo '失敗パターンAの場合の処理'
elif [ $? -eq 2 ] ; then
    echo '失敗パターンBの場合の処理'
fi

想定外の結果に

すると、 exit 1exit 2 のどちらの場合も「失敗パターンAの場合の処理」と出力されてしまいました。
パッと見は間違ってなさそうに見えるんですが、どうにもうまくいきません。なぜでしょう?

問題の原因

「とあるスクリプト」の実行後に if [ $? -eq 0 ] ; then の部分で  [ $? -eq 0 ] というコマンドが実行されます。
失敗パターンB(exit 2)の場合は [ 2 -eq 0 ] なので、判定は偽となり終了ステータスが 1 となります。
$? は「直前に実行した処理」の終了ステータスが格納される変数なので、 bash とあるスクリプト.sh を実行した際は $?2 がセットされていますが、 [ $? -eq 0 ] が実行されることにより $?1 に変わるわけです。
これにより、失敗パターンBの場合、 elif [ $? -eq 1 ] ; then の部分で [ $? -eq 1 ] というコマンドは [ 1 -eq 1 ] になってしまうので、判定は真となり「失敗パターンAの場合の処理」と出力されていたワケです。

解決方法

この問題を解決するにはどうしたらよいのでしょう?
$? が上書きされてしまうことが問題なので bash とあるスクリプト.sh を実行した直後に終了ステータスを変数にセットすることで解決します。

呼び出す側のスクリプト.sh
bash とあるスクリプト.sh
result=$?
if [ $result -eq 0 ] ; then
    echo '成功パターンの場合の処理'
elif [ $result -eq 1 ] ; then
    echo '失敗パターンAの場合の処理'
elif [ $result -eq 2 ] ; then
    echo '失敗パターンBの場合の処理'
fi

終了ステータスが2パターンから3パターンに増えて、これからも増えるかもしれないことを考慮すると、 elif をたくさん並べるよりも case に書き換えるというのもアリかもしれませんね。

呼び出す側のスクリプト.sh
bash とあるスクリプト.sh
result=$?
case $result in
    0 )
      echo '成功パターンの処理' ;;
    1 ) 
      echo '失敗パターンAの処理' ;;
    2 )
      echo '失敗パターンBの処理' ;;
esac

おまけ

ちょっと前に、「シェルスクリプトの「if」は条件式の「コマンド」の実行結果を判定している」という記事を書いてまして、 if の仕組みは理解していたつもりだったのにハマってしまいました。。。

参考URL

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1