LoginSignup
2
1

More than 3 years have passed since last update.

sh / Makefile で特定のエラーコードを無視したい

Last updated at Posted at 2020-04-10

TL; DR

shell スクリプトの場合

# エラーコード 1 を無視
cmd.sh || exit $(($? - 1))
# 複数のエラーコードを無視したい場合 (下記は 1, 2 を無視)
cmd.sh || ( exit $(($? - 1)) ) || ( exit $(($? - 1)) )

Makefile の場合

TARGET:
    # エラーコード 1 を無視
    cmd.sh || exit $$(($$? - 1))
    # 複数のエラーコードを無視したい場合 (下記は 1, 2 を無視)
    cmd.sh || ( exit $$(($$? - 1)) ) || ( exit $$(($$? - 1)) )

追記:こちらの方法ではエラーコードを変えるという荒っぽいことをしてますが、エラーコードを変えたくない場合の方法、コメントいただきました。よかったら、そちらもご覧ください。

はじめに

shell スクリプトや Makefile の処理で、「このエラーは処理を続けてほしいんだけど」みたいなこと、たまにありますよね。

sh だと

cmd.sh || true  # エラーコードが常に 0 になる

Make だと

TARGET:
    # 頭の "-" で、エラーを無視するようになる
    -cmd.sh

とかやると、エラーを無視してくれますが、あらゆるエラーが無視されます。そうなると、想定外のエラー発生時にも処理が進んでしまうので、できれば特定のエラー時だけ無視するようにしたいところです。

そこで

# エラーコード 1 を無視
cmd.sh || exit $(($? - 1))

1 のところを別の数値にすれば、好きなエラーコードを指定することができます。

|| は、前のコマンドがエラーコード 1 以上で終わった場合に、後ろのコマンドを実行するようにします。
$? で直前のコマンドのエラーコードとり、$(( )) で計算ができるので、1 を引いて、それを新しいエラーコードにしています。

これで、もしエラーコードが 1 なら新しいエラーコードが 0 になって、正常とみなされ処理が継続される、その他のエラーコードならやはり非 0 なので、エラーで停止する、という寸法です。

Makefile でも基本的に同じです。$$ としないと sh のコマンドに $ が渡らないので、そこだけ注意です。

TARGET:
    # エラーコード 1 を無視
    cmd.sh || exit $$(($$? - 1))

応用編: 複数のエラーコードを無視したい

複数のエラーコードを正常としたいときも、同じものをつなげていけばOK、、、なのですが、このままだと最初の exit で処理が終わってしまうので ( ) とサブシェルにしてあげましょう。(なお、sh スクリプトの場合に、後ろに処理がある場合も ( ) でくくってあげる必要があります)

# 複数のエラーコードを無視したい場合 (下記は 1, 2 を無視)
cmd.sh || ( exit $(($? - 1)) ) || ( exit $(($? - 1)) )

また、2 つめ以降の $? には、それまでの計算が反映された値が入るので、そこには注意が必要です。上の例の場合、2つめの exit-1 してますが、一つ前ですでに 1 引かれているので、最初のエラーコードが 2 の場合に、ここで 0 となります。

cmd.sh || ( exit $(($? - 1)) ) || ( exit $(($? - 2)) )

とすると、エラーコード 1, 3 を無視することになります。

あとがき

わりとよくあるニーズな気がするのですが、少しググってもページを見つけられなかったので、書いてみました。

「もっとよいやり方があるよ!」という方、ぜひ教えてもらえるとありがたいです :pray:

2
1
3

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
2
1