この質問を改善したいですか? この投稿を編集して、詳細を追加し、問題を明確にしてください。
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を受け取りません。
-
各コマンドは、自由に信号を処理できます。
sleep
SIGINTには特別なことは何もしないので、起動時に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
を取得するために実際に終了します の終了ステータス。