LoginSignup
1
1

More than 5 years have passed since last update.

trapがどんどん上書きされてしまう

Last updated at Posted at 2018-03-01

受け取ったシグナルに合わせて、指定した処理を実行してくれるtrap、とても便利ですよね(´・ω・`) 個人的には「作成した一時ファイルを終了後に必ず破棄する」という処理を実装する際によく利用しています。

path=$(mktemp)
trap "rm -f ${path}" EXIT

ひとつのシグナルに対する処理はそのスクリプト内において1回しか定義できない、つまりtrapを呼び出すたびにどんどん上書きされてしまうことに注意する必要があります。たとえば「複数の一時ファイルを作成し、処理終了後にそれらをすべて破棄する」とき、ついつい次のようなコードを書きがちです。

trap_test.sh
#!/bin/bash

set -x

path1=$(mktemp)
path2=$(mktemp)
path3=$(mktemp)

for path in ${path1} ${path2} ${path3}; do
  trap "rm -f ${path}" EXIT
done

# === do_something ===

exit 0

これを実行した結果が以下の通りになります。trapを3回呼び出して、作成した3つの一時ファイルを処理終了後に削除することを意図していますが、rmは一度しか呼ばれていません。また少しわかりづらいのですが、trapにより呼ばれたrmpath3を削除しています。つまりtrapは呼び出すごとに指定した処理を上書きしているとわかります。

$ bash trap_test.sh
++ mktemp
+ path1=/tmp/tmp.0dzHkNQP8n
++ mktemp
+ path2=/tmp/tmp.CtuP5ZdxyW
++ mktemp
+ path3=/tmp/tmp.8TZD5DRKKI
+ for path in '${path1}' '${path2}' '${path3}'
+ trap 'rm -f /tmp/tmp.0dzHkNQP8n' EXIT
+ for path in '${path1}' '${path2}' '${path3}'
+ trap 'rm -f /tmp/tmp.CtuP5ZdxyW' EXIT
+ for path in '${path1}' '${path2}' '${path3}'
+ trap 'rm -f /tmp/tmp.8TZD5DRKKI' EXIT
+ exit 0
+ rm -f /tmp/tmp.8TZD5DRKKI

したがって意図通りにするためには、trap_test.shを次のように修正する必要があります。

trap_test.sh
#!/bin/bash

set -x

path1=$(mktemp)
path2=$(mktemp)
path3=$(mktemp)
trap "rm -f ${path1} ${path2} ${path3}" EXIT

# === do_something ===

exit 0

この実行結果は以下の通りです。作成した3つの一時ファイルがrmの対象になっていることが確認できます(´・ω・`)

$ bash trap_test.sh
++ mktemp
+ path1=/tmp/tmp.vrVWvDvk9P
++ mktemp
+ path2=/tmp/tmp.i2aLRF3WMr
++ mktemp
+ path3=/tmp/tmp.Y6LOH2QYnw
+ trap 'rm -f /tmp/tmp.vrVWvDvk9P /tmp/tmp.i2aLRF3WMr /tmp/tmp.Y6LOH2QYnw' EXIT
+ exit 0
+ rm -f /tmp/tmp.vrVWvDvk9P /tmp/tmp.i2aLRF3WMr /tmp/tmp.Y6LOH2QYnw
1
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
1
1