以下はBASHスクリプトの例です。
#!/bin/bash
exithdl() {
echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}
trap exithdl EXIT
fun() {
echo "in fun subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "returned from fun"
}
echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2
実行すると、次の出力が生成されます。
subshell=0
trap -- 'exithdl' EXIT
in fun subshell=1
trap -- 'exithdl' EXIT
returned from fun
exiting
in exithdl subshell=0
サブシェル0と1のコマンドはtrap -p EXIT >&2
定義されたEXITトラップを表示しますが、このexithdl
機能はサブシェル0が終了した後にのみ実行されます。exithdl
シャットダウン後にサブシェル1が実行されないようにする方法はありますか?つまり、fun
この関数がEXITトラップなしでサブシェル1を決定できるように、1つ以上のコマンドを追加することは可能ですか?
例では、EXIT トラップはサブシェル 0 に対して定義されていますが、サブシェル 1 では定義されていません。このtrap -p EXIT
コマンドは、両方のサブシェルで実行されたときにまったく同じ出力を表示します。したがって、trap -p EXIT
特定のサブシェルにトラップがあるかどうかを確認するためには使用できないとします。私はtrap -p EXIT
コマンドが実行されたときにEXITトラップの存在を示すことを認めていますfun
が、funが返されたときにEXITトラップが実行された場合は表示されません。私は何を逃したことがありませんか?
答え1
バッシュ3を使用する場合
答えは、使用しているbashのバージョンによって異なります。たとえば、私のMacにはmacOS High SierraがデフォルトでインストールされていますGNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
。この場合、以下のようにtrap -p EXIT >&2
関数のコマンドに括弧を追加することで問題を解決できます。fun
#!/bin/bash
exithdl() {
echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}
trap exithdl EXIT
fun() {
echo "in fun subshell=$BASH_SUBSHELL" >&2
(trap -p EXIT >&2) # <--- See Here
echo "returned from fun"
}
echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2
以下に示す結果出力にはトラップのあるfun
機能は表示されません。EXIT
subshell=0
trap -- 'exithdl' EXIT
in fun subshell=1
returned from fun
exiting
in exithdl subshell=0
この方法は、他のトラップのサブセットにも適用されます。たとえば、このサブセットには、およびINT
トラップが含まれますQUIT
。ただし、このサブセットにはその他の問題は含まれません。TERM
CHLD
HUP
Bash 4と5を使用する場合
VirtualBoxにUbuntu 18と19もインストールしました。これらのオペレーティングシステムはデフォルトでそれぞれとGNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
を使用しますGNU bash, version 5.0.11(1)-release (x86_64-pc-linux-gnu)
。上記の変更を適用してスクリプトを実行すると、結果は元の出力と同じです。ただし、これらの最新バージョンのbashの場合は、trap
以下のように機能のコマンドの前にコマンドを追加することで問題を解決できます。trap -p EXIT >&2
fun
#!/bin/bash
exithdl() {
echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}
trap exithdl EXIT
fun() {
echo "in fun subshell=$BASH_SUBSHELL" >&2
trap -- KILL # <--- See Here
trap -p EXIT >&2
echo "returned from fun"
}
echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2
トラップを変更できないため、このtrap -- KILL
コマンドが選択されました。KILL
これにより、上記の画像と同じ出力が生成されます。この方法は他のトラップにも適用されます。
結論として
exitTrap
現在のトラップを定義するために使用されるコマンドの変数を設定するには(たとえば)、EXIT
以下のスクリプトを使用します。これはbash 3、4、5で動作します。
trap -- KILL
exitTrap="$( (trap -p EXIT) )"