bashで+を使用してCtrlSIGINTに対して2つのテストを実行しました。C
テスト1
親スクリプトとサブスクリプトの両方でハンドラを設定しますtrap
。
# !/bin/bash
# Parent.sh
trap 'echo "I handled the SIGINT in Parent.sh and expect the script going ahead."' SIGINT
echo 1.1
./Child.sh
echo 1.2
# !/bin/bash
# Child.sh
trap 'echo "I handled the SIGINT in Child.sh and expect the script going ahead."' SIGINT
echo 2.1
sleep 1000000000
echo 2.2
/tmp:$ ./Parent.sh
1.1
2.1
^CI handled the SIGINT in Child.sh and expect the script going ahead.
2.2
I handled the SIGINT in Parent.sh and expect the script going ahead.
1.2
出力は私が予想したものとほぼ同じです。
テスト2
サブスクリプトのみ設定ハンドラを渡しますtrap
。
# !/bin/bash
# Parent.sh
# trap 'echo "I expect I will be terminated immediately after Child.sh died."' SIGINT
echo 1.1
./Child.sh
echo "sleep started"
sleep 5
echo "sleep finished"
echo 1.2
# !/bin/bash
# Child.sh
trap 'echo "I handled the SIGINT in Child.sh and expect the script going ahead."' SIGINT
echo 2.1
sleep 1000000000
echo 2.2
/tmp:$ ./Parent.sh
1.1
2.1
^CI handled the SIGINT in Child.sh and expect the script going ahead.
2.2
sleep started
sleep finished
1.2
私はParent.sh
これが死後直ちに終了しなければならないと予想しました(SIGINTの基本措置として)Child.sh
。
しかし、SIGINTを受けたようですがParent.sh
無視します。
なぜですか?
答え1
このようなことが起こる理由は「待って協力していきましょう」(WCE)bash
実装。
bashが子SIGINT
プロセスを待っている間にシグナルを受信すると、そのシグナルによって子プロセスが終了した場合にのみ(子プロセスが終了するのではなく)、自らが終了します。親WIF*
プロセスは、子プロセスの終了状態を介して、未処理の信号によって終了したか終了したかを確認できます。wait(2)
マンページ。
より簡単な例:
bash -c 'sh -c "trap exit INT; read p"; echo DONE'
<ctrl-C>
DONE
そしてdash
WCEを実装しないシェル:
dash -c 'sh -c "trap exit INT; read p"; echo DONE'
<ctrl-C>
<no DONE, parent script was killed outright>