関数レベルのbashトラップ(トラップ... RETURN)を使用したときの「バインドされていない変数」エラー

関数レベルのbashトラップ(トラップ... RETURN)を使用したときの「バインドされていない変数」エラー

関数を呼び出してその関数にtrap設定する次のスクリプトを検討してくださいRETURN

#!/usr/bin/env bash
set -euo pipefail

function f1() {
  local temp_file
  temp_file="$(mktemp)"
  trap 'echo DELETED; rm -- "${temp_file}"' RETURN
  date > temp_file
}

function main() {
  for i in $(seq 0 2); do
    f1
  done
}

main

何らかの理由で、DELETED文字列は3回ではなく4回印刷され、次のunbound variableエラーで失敗します。

DELETED
DELETED
DELETED
DELETED
hack/deploy-example-server.sh: line 13: temp_file: unbound variable

明らかに何かがthisをさらに実行しているようですtrap。スクリプト全体が終了しているようです。

function mainf1最上位スクリプトからforループを削除して呼び出すだけでは、これは発生しません。

この動作の原因は何ですか?

答え1

設定した内容はすべてtrapグローバルです。

4番目のトラップはmain()戻ってきたときに発生します。この時点では、local変数はtemp_file設定されなくなりました。 (したがってunbound variableエラーが発生します。)

main()ループ後にトラップをキャンセルすることを検討してくださいfor。武装解除トラップが使えると思いますtrap RETURN

または(最高ですか?)使用を検討してくださいtrap

オプション1:削除する各ファイルを配列に追加し、後で明示的にファイルを削除します。

オプション2:f1()関数を別の関数にラップし、f2()ファイルf2()を削除します。おそらく次のようになります(テストしたことはありません)。

#! /usr/bin/env bash

set -euo pipefail

function trace() {
  #  usage:  trace  command  [arg ...]
  echo  "+  $*"  1>&2
  "$@"
}

function f1() {
  true    #  replace true with your code
}

function f2() {
  #  usage:  f2  func_name
  local func_name="$1"
  local temp_file="$(mktemp)"
  "$func_name"
  trace  rm  --  "$temp_file"
}
    
function main() {
  for i in $(seq 0 2); do
    f2  f1
  done
}

main

関連情報