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


14

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

#!/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サブシェルに継承されますか?

回答:


10

トラップハンドラはサブシェルに継承されません。これはPOSIX指定されています:

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

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


3
bash set -Eでは、サブシェルにトラップを継承させることができますが、正しく処理するのは本当に難しいです(少なくとも私の経験では)。
dragon788

これがすべてのトラップで機能するかどうかはわかりません。私はそれがERRのために働くことを知っています
-yosefrow

4

trapはサブシェルに伝播されませんが、サブシェルが親シェルのトラップを報告できる方法とそうでない方法があります。macashで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)"

fifoが機能しないのはbash 3.2.57trap &ために空でbash 3.2.57はなく、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

2

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

検証者:

trap "echo bla" 1 2 3"

(trap)


2
多くのシェル(trap)は特殊なケースとして処理するため、サブシェルは親シェルのトラップを報告できます(実際には使用しません)。そのため、そのテストは常に信頼できるとは限りません。
JigglyNaga

これはBourne Shellで動作し、派生物:ksh88bosh(Schily Bourne Shell)およびheirloom-sh。あなたは正しいです:ksh93異なる動作をします。
気味悪い

問題のスクリプトが使用するbashでは機能しません。
JigglyNaga

まあ、それはbash で動作します:bashを呼び出しても何も出力しません(trap)
気味悪い
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.