QA@IT

set -eは使うべき?使わないべき?

4007 PV

シェルスクリプトを書くときに、shebangの直後にset -eをつけるかどうかで迷っています。

具体的には、自分で書いたデーモンサーバのinitスクリプトです。

たしか昔にset -eはつけるな、というのをどこかで学んで、それ以降、なんとなくそれに従ってきていたのですが、たとえばUnicornの例もそうですが、set -eをつけている例をよく見るようになってきました。

そこで、自分がset -eの良し悪しについて判断するだけの経験値を持っていないことに気が付きました。

つけた場合・つけない場合の良いところ・悪いところについて、ご存知のことがあれば教えてください。

回答

完全に自分で書く場合は出来るだけ set -e を付けるようにしています。

利点としては

  • exit status を常に気にすることが出来る。
  • 途中で予想外の失敗があった時にそのまま気付かずに進んでしまって変になることを防ぎやすい。

欠点としては

  • diff や cmp などで 0 以外を期待する処理がちょっと書きにくい。
  • set -e での動作を想定していないライブラリを . (ドット) コマンド や source コマンドで読み込んだときに使えない。

ということがあります。

Debian や Ubuntu は後者の欠点から、 set -e は使わない方が良いということになっているように見えます。

http://www.debian.org/doc/debian-policy/ch-opersys.html

Be careful of using set -e in init.d scripts. Writing correct init.d scripts requires accepting various error exit statuses when daemons are already running or already stopped without aborting the init.d script, and common init.d function libraries are not safe to call with set -e in effect[81]. For init.d scripts, it's often easier to not use set -e and instead check the result of each command separately.

/etc/init.d/skeleton にも # Do NOT "set -e" と書いてありました。

http://wiki.debian.org/LSBInitScripts/StatusSupport には set -e (as recommended), という記述もあるので、推奨だった時期もあったのかもしれません。

編集 履歴 (0)
  • ありがとうございます!distro自体がset -eについて言及していることに気がついていませんでした。たしかに外部ライブラリを読み込むときに気をつけないといけませんね。まさしく知りたい内容でした。 -

悪い点:

  • エラー処理を行えない (一時ファイルの削除など)
  • exitしない場合(返り値を文法上明確に処理している場所)の ことをつい忘れてしまう

良い点:

  • $?の確認をいちいちしなくてもいい
  • 想定していない状態でスクリプトが先まで走ってしまうことを(一部)防げる

、ということで、「ちゃんと書く」場合は使わない、
開発中などで、「ちゃちゃっと書く」場合は使うのが良いのではないでしょうか?

編集 履歴 (0)
  • ありがとうございます。質問の意図としては、「ちゃんと書く」場合でもset -eを積極的に使うケースが増えてるのではないか、ということでした。failing_command || rescue_commandのようにOR条件を書けば明示的にエラー処理も行えるようです。「exitしない場合のことをつい忘れてしまう」について補足いただけませんか? -
ウォッチ

この質問への回答やコメントをメールでお知らせします。