この質問を改善したいですか? この投稿を編集して、詳細を追加し、問題を明確にしてください。
3年前に閉鎖されました。
この質問を改善する
理解する
Bashがコマンドの完了を待機している場合 トラップが設定されている
の信号を受信すると、
コマンドが完了するまでトラップは実行されません。Bashがwaitビルトインを介して非同期コマンドを待機している場合 、
トラップが設定された信号を受信すると、
待機ビルトインは、
128を超える終了ステータスですぐに戻り、その直後にトラップが実行されます。
/ P>
Bashマニュアルから、
私は以下を実行します:
-
私の2つの例では、SIGINT(Ctrl-Cで送信)は、
フォアグラウンドジョブ(引用符の最初のケース)とバックグラウンドジョブ(引用符の2番目のケース)の両方を、待機せずにすぐに終了します。
それらを完了するために。引用符の最初の文は、Bashが
フォアグラウンドジョブを実行していて、シグナルSIGINTを受信した場合を意味しますか? 、シグナルのトラップ
SIGINT、設定すると、コマンドが完了するまで実行されますか?
はいの場合、最初の例でctrl-Cを実行するのはなぜですか フォアグラウンドを作成します
ジョブが完了する直前に存在しますか?$ sleep 10000 # a foreground job ^C $ sleep 10000 & # a background job [1] 21219 $ wait 21219 ^C $ echo $? 130 -
「トラップが設定された信号」とは何ですか つまり、
-
シグナル
argそのトラップはtrap arg sigspecを介して指定されています 、または -
無視されない信号、または
-
トラップがデフォルトではない信号?
パート1の例では、SIGINTのトラップを設定しなかったため、シグナルには
デフォルトハンドラーがあります(実行中のループから抜け出します)。
デフォルトのハンドラーを持つシグナル
設定されたトラップがあると見なされますか? -
-
SIGINTのトラップを設定しました 、ただしctrl-C完了する前に、次の
コマンドを終了します。それで、それは私の引用の最初の
文に反していますか?$ trap "echo You hit control-C!" INT $ bash -c 'sleep 10; echo "$?"' ^C $SIGINTのトラップを設定する前 、ctrl-Cまた、完了する前に
同じコマンドを終了します。それで、それは私の引用の最初の
文に反していますか?$ bash -c 'sleep 10; echo "$?"' ^C -
引用の2つの文が何を意味するかを説明するためにいくつかの例を挙げていただけますか?
ありがとう。
承認された回答:
「トラップが設定された信号」とはどういう意味ですか?
これは、ハンドラーが定義されているシグナルです(trap 'handling code' SIG )処理コードが空でない場合、シグナルが無視される原因になります。
したがって、デフォルトの性質を持つシグナルは、トラップが設定されたシグナルではありません。
投稿の引用の一部は、デフォルトの性質を持つシグナルにも適用されますが、トラップ 、トラップが定義されていないため。
マニュアルでは、シェルへの信号配信について説明しています。 、そのシェルから実行するコマンドではありません。
1。
Bashがコマンドの完了を待機している場合 トラップが設定されている信号を受信すると、コマンドが完了するまでトラップは実行されません。
(1)
私の最初の例で、ctrl-Cがフォアグラウンドジョブを完了する直前に終了させるのはなぜですか
sleep 10を実行した場合 インタラクティブシェルのプロンプトで 、シェルはそのジョブをフォアグラウンドに配置します (ioctl()を介して どのプロセスグループがフォアグラウンドグループであるかを端末回線の規律に伝えるttyデバイスでは)、sleepのみ ^CでSIGINTを取得します インタラクティブシェルは 、そのため、その動作をテストすることは役に立ちません。
-
親シェルは、そのプロセスがフォアグラウンドプロセスグループにないため、インタラクティブであるためSIGINTを受け取りません。
-
各コマンドは、自由に信号を処理できます。
sleepSIGINTには特別なことは何もしないので、起動時にSIGINTが無視されていない限り、デフォルトの処理(終了)を取得します。
(2) sleep 10を実行した場合 非対話型シェルで 、
bash -c 'sleep 10; echo "$?"'
非対話型のbashの両方 シェルとsleep Ctrl-Cを押すとSIGINTを受け取ります。
bashの場合 すぐに終了すると、sleepが残る可能性があります SIGINTシグナルを無視または処理した場合、コマンドはバックグラウンドで無人で実行されます。代わりに
-
bash他のほとんどのシェルと同様に、ブロック コマンドを待っているときの信号(少なくともいくつかの信号)の受信。 - コマンドが終了すると(トラップが実行されると)、配信が再開されます。これにより、トラップ内のコマンドが他のコマンドと同時に実行されることも回避されます。
上記の例では、sleep SIGINTで死ぬので、bash 独自のSIGINTを処理するのを待つのに長くはかかりません(trapを追加しなかったのでここで死にます SIGINTで)。
(3)非対話型シェルの実行中にCtrl + Cを押した場合:
bash -c 'sh -c "trap "" INT; sleep 3"; echo "$?"'
(trapなし SIGINTで)bash SIGINTによって殺されることはありません。 bash 、他のいくつかのシェルと同様に、SIGINTとSIGQUITを特別に扱います。 待機と協調出口を実装します https://www.cons.org/cracauer/sigint.htmlで説明されている動作(^Cで中断できないSIGINT処理コマンドを呼び出すスクリプトのように、いくつかの煩わしさを引き起こすことが知られています。 )
(4)適切にテストするには、非対話型のbashを実行する必要があります SIGINTトラップが設定されている SIGINTですぐに死なないコマンドを呼び出します のように:
bash -c 'trap "echo Ouch" INT; sh -c "trap "" INT; sleep 3"'
bash shを待っています それは(sleepと共に) )SIGINTは無視されます(trap "" INTのため) )、したがってSIGINTはsleepを強制終了しません また、sh 。 bash SIGINTを無視しませんが、その処理はshまで延期されます。 戻り値。 Ouchが表示されます Ctrl + C ではなく、表示されている 、ただしsleepの後 およびsh 正常に終了しました。
trapに注意してください コマンドは、それが実行されているのと同じシェルの信号のトラップを設定します。したがって、trap コマンドは、非対話型シェルの外部および親シェルで実行されます。
$ trap "echo You hit control-C!" INT $ bash -c 'sleep 10; echo "$?"' ^C $
非対話型のbash 、およびsleep コマンドはそのtrapを継承しません 親シェルから。別のコマンド(execve()を実行すると、シグナルハンドラーが失われます ハンドラーのコードを含むプロセスのアドレス空間全体をワイプします)。 execve()の場合 、ハンドラーが定義されたシグナルはデフォルトの配置に戻り、無視されたシグナルは無視されたままになります。
それに加えて、ほとんどのシェルでは、trap sもサブシェルでリセットされます。
2。
Bashがwaitビルトインを介して非同期コマンドを待機している場合 、トラップが設定された信号を受信すると、待機ビルトインは128を超える終了ステータスですぐに戻り、その直後にトラップが実行されます。
waitを使用する場合 明示的に 、wait トラップが設定されている信号(および明らかにシェルを完全に殺す信号)によって中断されます。
そのため、トラップされた信号がある場合にコマンドの終了ステータスを確実に取得することは困難です :
$ bash -c 'trap "echo Ouch" INT; sh -c "trap "" INT; sleep 10" & wait "$!"; echo "$?"'
^COuch
130
その場合、sleep およびsh SIGINTによって殺されませんでした(彼らはそれを無視しているため)。それでもwait 130で返されます shの待機中にシグナル(SIGINT)を受信したため、終了ステータス 。 wait "$!"を繰り返す必要があります shまで shを取得するために実際に終了します の終了ステータス。