Last Modified:
同じシグナルに複数個のtrapを仕掛ける方法 #Shell
同じシグナルに何個かtrap
を仕掛けたいけど、trap
は上書きされてしまうので最後に仕掛けたコマンドしか実行されない。
解決
ちょっとやっつけな感じだけど、 trap -p
で現在の内容が出力されるので
at_exit () {
trap "$1 ; $(trap -p EXIT | sed -E "s/^trap -- '(.*)' EXIT\$/\\1/")" EXIT
}
at_exit 'echo first'
at_exit 'echo second'
ってな感じで;
で繋いだコマンドで再定義していけば追記していける。
汎用的にする
汎用的にするため、trap
を正しく再定義すればこうなる。
trap () {
if ((($# == 3)) && [[ $1 == '--' ]]) || ((($# == 2)) && [[ ${1:0:1} != '-' ]])
then
if (($# == 3)) && [[ $1 == '--' ]]
then
shift
fi
set -- -- "$1 ; $(builtin trap -p -- "$2" | sed -E "s/^trap -- '(.*)' $2\$/\\1/")" "$2"
fi
builtin trap ${1+"$@"}
}
実行結果
# 素のtrapは上書きされてしまう
$ cat foo.sh
trap 'echo first' EXIT
trap 'echo second' EXIT
$ bash foo.sh
second
# trapを再定義すると追記が可能
$ cat foo.sh
trap () {
if ((($# == 3)) && [[ $1 == '--' ]]) || ((($# == 2)) && [[ ${1:0:1} != '-' ]])
then
if (($# == 3)) && [[ $1 == '--' ]]
then
shift
fi
set -- -- "$1 ; $(builtin trap -p -- "$2" | sed -E "s/^trap -- '(.*)' $2\$/\\1/")" "$2"
fi
builtin trap ${1+"$@"}
}
trap 'echo first' EXIT
trap 'echo second' EXIT
$ bash foo.sh
second
first
- bashじゃないと動かないですよ。
- 登録した順序とは逆順に動くようにしています。おそらくその方が想定通りだと思いますので。
builtin trap
を正しく再定義するために--
辺りを処理してます。