LoginSignup
15
10

More than 5 years have passed since last update.

シェルスクリプトのtrapほかの落とし穴

Posted at

シェルスクリプトを書いていたところで、set -etrapの挙動に引っかかってしまいました。

なお、「特定の環境で動けばいい」という前提なので、シバンの段階で#!/bin/bashと決め打っています。POSIXへの準拠性などは考えません。

関数化したら、意図しない動作に

似たような動作をするシェルスクリプトがあったので、一部を関数にして切り出すことにしました。set -etrap ERRの組み合わせで、エラー時の終了処理はもともと組んでありました。


# main.sh

source ./functions.sh

failure() {
  echo エラー発生!
}

trap failure ERR

set -e

func

echo 正常終了

# functions.sh

func() {
  # 処理失敗のシミュレーション
  false 
  echo 'func complete'
}

さて、上のコードを実行すれば、何を表示するでしょうか。意図としては、「エラー発生!」だけになってほしいのです…が、なんと何も表示せず終了してしまいます

動作確認と狙い通りな形への改造

何が起きたのかと調べてみると、以下のような動作をしていたのでした(manより)。

  • set -e…関数内まで適用される
  • trap ERR…関数内にはデフォルトでは適用されない

ということで、関数内のエラーではtrapに入らず即座に終了してしまう、という挙動となっていました。

そして、set -Eとすればtrap ERRが関数にも適用される、ということでやってみたら、今度はエラーが2回表示されるようになりました。今回の場合、一度trap ERRに入れば復帰する目がなかったので、そのままtrapの関数の中でexitさせることで、2回目が来る前に終了させて解決しました。

set -E

failure() {
  echo エラー発生!
  exit 1
}

教訓

いざという時、manは役に立つ

15
10
2

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
15
10