次のスクリプトを試しました。
#!/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
サブシェルに継承されますか?
答え1
トラップハンドラはサブシェルから継承されません。これはPOSIXで指定:
無視されないトラップは、サブシェルに入るとデフォルトの動作に設定されます。
無視された信号(trap '' SIGFOO
)は、サブシェル(およびシェルによって開始された外部プログラム)ではまだ無視されます。
答え2
trap
サブシェルには伝播されませんが、一部の方法では、サブシェルが親シェルにトラップを報告できるようにし、他の方法ではそうではありません。 bashを使ってmacOSでいくつかのテストを行いました。
GNU bash、バージョン 4.4.12(1)-リリース(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)-リリース(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.57
ので動作しませんが、そうではありません。trap &
bash 3.2.57
bash 4.4.12
GNU bash、バージョン 4.4.12(1)-リリース(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)-リリース(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
答え3
trap
定義はサブシェルに伝播されません。
識別方法:
trap "echo bla" 1 2 3
(trap)
答え4
サブシェルを呼び出すと、親trap
トラップが表示されますが、サブシェルでは実行されません。サブシェルに新しいトラップを設定できます。
これをテストするには、次のコードを使用してスクリプトを生成して実行し、ctrl+を実行しますc。
#!/usr/bin/bash
function sub { echo sub_before: `trap`; trap 'echo kill_sub; exit' SIGINT; echo sub_after: `trap`; while :; do sleep 1; done; }
function parent { echo parent_before: `trap`; trap 'pkill -2 -P $$; echo kill_parent; exit' SIGINT; echo parent_after: `trap`; sub & wait; }
parent
両方のトラップが実行されていることがわかります。
(Bash 5.0.17)