理解する
Bashがコマンドが完了するのを待つ場合トラップが確立されたことを知らせると、コマンドが完了するまでトラップは実行されません。
Bashがwait組み込み関数を介して非同期コマンドを待つ場合、トラップを設定した信号を受信すると、内蔵待機が128より大きい終了状態に即座に返され、すぐにトラップが実行されます。
Bashのマニュアルによると、次のコマンドを実行します。
どちらの例でも、SIGINT(Ctrl-Cで送信)は、フォアグラウンドジョブ(引用符の最初のケース)とバックグラウンドジョブ(引用符の2番目のケース)が完了するのを待たずにすぐに終了します。
引用の最初の文は、Bashがフォアグラウンドジョブを実行してsignalを受け取ると、コマンドが完了するまで信号のトラップが
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
または無視されない信号、または
トラップはデフォルトのトラップではないシグナルですか?
Part 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つの文が何を意味するのかを説明するために、いくつかの例を挙げることができますか?
ありがとうございます。
ベストアンサー1
「閉じ込められた信号」とはどういう意味ですか?
これは、ハンドラコードが空でない場合(を使用して)定義されたハンドラを持つ信号です。trap 'handling code' SIG
これにより信号は無視されます。
したがって、基本構成の信号はトラップされた信号ではありません。投稿の引用の一部は、基本設定のシグナルにも適用されます。トラップを実行する、トラップが定義されていないからです。
マニュアルでは、シグナル伝達について説明します。皮をむく、そのシェルで実行するコマンドではありません。
1.
Bashがコマンドが完了するのを待つ場合トラップが確立されたことを知らせると、コマンドが完了するまでトラップは実行されません。
(1)
最初の例では、ctrl-Cがフォアグラウンド操作を完了する直前に終了するのはなぜですか?
sleep 10
対話型シェルのプロンプトで実行されている場合、シェルは仕事を展望(ioctl()
ttyデバイスのプロセスグループを介して、どのプロセスグループが前景プロセスグループであるかをターミナルラインルールに通知します)SIGINT のみsleep
受信され、^C
対話型シェルは受信されません。したがって、この動作をテストすることは役に立ちません。
親シェルは対話型であるため、そのプロセスはフォアグラウンドプロセスグループに属していないため、SIGINTを受け取りません。
各コマンドは必要に応じて信号を処理できます。
sleep
SIGINTに対して特別な操作は行われないため、起動時にSIGINTが無視されない限り、基本構成(終了)が取得されます。
(2)sleep 10
非対話型シェルで実行している場合、
bash -c 'sleep 10; echo "$?"'
bash
非対話型シェルとシェルの両方がCtrl-Cを押すとsleep
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(少し迷惑を引き起こすことが知られています。SIGINT処理コマンドを呼び出すスクリプトは中断できません。^C
)
(4) 正しくテストするには、次のことを行う必要があります。非対話型で実行bash
それSIGINT トラップセットそして電話してくださいSIGINT直後に終了しないコマンド良い:
bash -c 'trap "echo Ouch" INT; sh -c "trap \"\" INT; sleep 3"'
bash
sh
(同様に)SIGINTを待つことはsleep
無視されるので、SIGINTはどちらもtrap "" INT
終了しません。 SIGINTは無視されませんが、返されるまで処理が遅れます。表示される画面はオンになっているのではなく、通常の終了後に表示されます。sleep
sh
bash
sh
Ouch
Ctrl+Csleep
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
この場合、SIGINTによってsleep
殺されませsh
んでした(無視したためです)。待機中に信号(SIGINT)が受信されたため、終了ステータスは依然としてwait
返されます。終了ステータスを取得するには、実際に終了するまで繰り返す必要があります。130
sh
wait "$!"
sh
sh