TL; DR
shell スクリプトの場合
# エラーコード 1 を無視
cmd.sh ||exit$(($?-1))# 複数のエラーコードを無視したい場合 (下記は 1, 2 を無視)
cmd.sh || sh -c"exit $(($?-1))"|| sh -c"exit $(($?-1))"
Makefile の場合
TARGET:# エラーコード 1 を無視
cmd.sh||exit$$(($$?-1))# 複数のエラーコードを無視したい場合 (下記は 1, 2 を無視)
cmd.sh||sh-c"exit $$(($$? - 1))"||sh-c"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、、、なのですが、少し一工夫して sh -c "..."
でくくってあげましょう。そうしないと、最初の exit
で処理が終わってしまい、意図した動作になりません。
# 複数のエラーコードを無視したい場合 (下記は 1, 2 を無視)
cmd.sh || sh -c"exit $(($?-1))"|| sh -c"exit $(($?-1))"
また、2 つめ以降の $?
には、それまでの計算が反映された値が入るので、そこには注意が必要です。上の例の場合、2つめの exit
も -1
してますが、一つ前ですでに 1
引かれているので、最初のエラーコードが 2
の場合に、ここで 0
となります。
cmd.sh || sh -c"exit $(($?-1))"|| sh -c"exit $(($?-2))"
とすると、エラーコード 1
, 3
を無視することになります。
あとがき
わりとよくあるニーズな気がするのですが、少しググってもページを見つけられなかったので、書いてみました。
「もっとよいやり方があるよ!」という方、ぜひ教えてもらえるとありがたいです