web-dev-qa-db-ja.com

トラップはサブシェルに継承されますか?

私は次のスクリプトを試しました:

#!/bin/bash
trap 'echo "touching a file" && touch $FILE' EXIT

foo1(){
        echo "foo1"
}
foo(){
        echo "foo"
        export FILE=${FILE:-/tmp/file1}
}
(foo1)
foo

上記のスクリプトの出力は次のとおりです。

[root@usr1 my_tests]# ./test.sh
foo1
foo
touching a file

ただし、サブシェルで呼び出されるfoo1の終了時にトラップが呼び出されることを期待していました。

  • これは予想されますか?
  • trapはサブシェルに継承されますか?
  • はいの場合、どのケースでtrapはサブシェルによって継承されますか?
14

トラップハンドラーがサブシェルに継承されることはありません。これは POSIXで指定 です。

サブシェルに入ると、無視されないトラップがデフォルトのアクションに設定されます。

無視された信号(trap '' SIGFOO)サブシェル(およびシェルによって起動された外部プログラム)でも無視されます。

trapはサブシェルに伝播されませんが、サブシェルが親シェルのトラップを報告できるようにする方法と、そうでない方法があります。 macosでbashを使用していくつかのテストを行いました。

GNU bash、バージョン4.4.12(1)-release(x86_64-Apple-darwin16.3.0):

_trap 'echo hello' EXIT
trap # trap -- 'echo hello' EXIT
echo "$(trap)" # trap -- 'echo hello' EXIT
trap | cat # trap -- 'echo hello' EXIT
(trap) | cat # trap -- 'echo hello' EXIT
cat < <(trap) # empty
cat <<< "$(trap)" # empty
bash -c 'trap' # empty
trap & # trap -- 'echo hello' EXIT
_

GNU bash、バージョン3.2.57(1)-release(x86_64-Apple-darwin16):

_trap 'echo hello' EXIT
trap # trap -- 'echo hello' EXIT
echo "$(trap)" # trap -- 'echo hello' EXIT
trap > >(cat) # trap -- 'echo hello' EXIT
trap | cat # empty
(trap) | cat # empty
cat < <(trap) # empty
cat <<< "$(trap)" # empty
bash -c 'trap' # empty
trap & # empty
_

これは、trap_output="$(trap)"がトラップ出力をキャプチャするように機能することを知っておくと役立ちます。 _trap >trap_output_file_を実行してファイルに出力し(fifoは_bash 3.2.57_で機能しない)、それを再度読み取る以外にそれが機能しない場合、他の方法は考えられませんtrap_output="$(<trap_output_file)"

_bash 3.2.57_は_trap &_では空ですが_bash 3.2.57_では空なので、fifoは_bash 4.4.12_では機能しません。

GNU bash、バージョン4.4.12(1)-release(x86_64-Apple-darwin16.3.0):

_mkfifo /tmp/fifo; trap >/tmp/fifo & trap_output=$(</tmp/fifo); rm -f /tmp/fifo; echo "$trap_output"
# trap -- 'echo hello' EXIT

mkfifo /tmp/fifo; trap_output=$(</tmp/fifo) & trap >/tmp/fifo; rm -f /tmp/fifo; echo "$trap_output"
# empty because trap_output=$(</tmp/fifo) sets the variable in a subshell
_

GNU bash、バージョン3.2.57(1)-release(x86_64-Apple-darwin16):

_mkfifo /tmp/fifo; trap >/tmp/fifo & trap_output=$(</tmp/fifo); rm -f /tmp/fifo; echo "$trap_output"
# empty because trap >/tmp/fifo & is empty since it uses trap &

mkfifo /tmp/fifo; trap_output=$(</tmp/fifo) & trap >/tmp/fifo; rm -f /tmp/fifo; echo "$trap_output"
# empty because trap_output=$(</tmp/fifo) sets the variable in a subshell
_
5
dosentmatter

trap定義はサブシェルに伝播されません。

確認する:

trap "echo bla" 1 2 3"

(trap)

2
schily