次のシェルスクリプトがある場合
sleep 30s
Ctrl+Cシェルスクリプトの実行中にクリックするとsleep
消えます。
次のシェルスクリプトがある場合
sleep 30s &
wait
Ctrl+Cシェルスクリプトが実行されたら、[続行]をクリックしましたが、親のsleep
エントリは1です。
なぜそんなことですか?バッシュはCtrl+Cすべての子供に広がりませんか?
編集:次のスクリプトがある場合
/usr/bin/Xvfb :18.0 -ac -screen 0 1180x980x24 &
wait
私はプログラムを作成しており、今回はCtrl+C基本プロセスのXvfb
プロセスも終了します。
それでは、Xvfb
睡眠とどう/なぜ違うのですか?
場合によってはリサイクルされており、場合init
によっては死んでいました。 initが睡眠をリサイクルするのはなぜですか?なぜXvfb
死なのか?
答え1
長すぎる博士。プロセスXvfb
はシグナルハンドラを設定し、SIGINT
そのようなシグナルが受信されると終了しますが、プロセスはそれをしsleep
ないので、SIGINT
バイナリを実行する前にスクリプトを実行したシェルで設定したため、「無視」状態を継承しますsleep
。
シェルスクリプトを実行すると、ジョブ制御がオフになり、バックグラウンドプロセス(で始まるプロセス)は(無視)に設定された&
同じプロセスグループでのみ実行され、標準入力は次からリダイレクトされます。SIGINT
SIGQUIT
SIG_IGN
/dev/null
これは次のために発生します。基準:
シェルが非同期リストを実行しているときにジョブ制御が無効になっている場合(set -mの説明を参照)、リストのコマンドはシェルのSIGINTおよびSIGQUITシグナルの無視(SIG_IGN)シグナル操作を継承します。
信号処理が(無視)に設定されている場合、ステータスはおよびによってSIG_IGN
継承されます。fork()
execve()
:
呼び出しプロセスイメージでデフォルトアクション(SIG_DFL)に設定されている信号は、新しいプロセスイメージでもデフォルトアクションに設定する必要があります。 SIGCHLDに加えて、呼び出しプロセスイメージが無視されるように設定された信号(SIG_IGN)も、新しいプロセスイメージによって無視されるように設定する必要があります。
答え2
~からバッシュのマニュアルページ:
バックグラウンドプロセスは、プロセスグループIDがターミナルプロセスグループIDと異なるプロセスを意味し、これらのプロセスはキーボードから生成された信号の影響を受けません。
これをさまざまな方法で処理できます。まず、リストされたジョブを終了します。
#!/bin/bash
trap 'kill $(jobs -p)' INT
sleep 30s &
wait
または、同じプロセスグループ内のすべてのプロセスにkillコマンドを送信します。
#!/bin/bash
trap 'kill 0' INT
sleep 30s &
wait
答え3
Bashは、SIGINTやSIGTERMなどの信号を現在待機しているプロセスに転送しません。
一般的な回避策は、次の例のようにトラップ待機を実行することです。
int_handler()
{
kill -TERM "${child_pid}" > /dev/null 2>&1
}
trap 'int_handler' INT
echo "Sleeping ... "
sleep 200 &
child_pid=$!
wait ${child_pid} > /dev/null 2>&1
trap - INT
wait ${child_pid} > /dev/null 2>&1