bashスクリプトでSIGQUITを適切にトラップするにはどうすればよいですか?
質問
SIGINT
をうまくトラップするシェルスクリプトを書くことはできますが、SIGQUIT
をトラップできないようです。
ジェネラコディセタグプレ
このスクリプトを実行してCTRL-C
を押すと目的の効果が得られますが、CTRL-\
を押すと(私が理解しているように、SIGQUIT
がトリガーされます)、ターミナルに^\
を出力する以外は何もしません。なぜですか?
私には2つの実行理論があります。 1つ目は、SIGINT
とSIGQUIT
のセマンティクスが異なるため、SIGQUIT
は子プロセスsleep
にのみ送信され、SIGINT
は子プロセスと親bashプロセスの両方に送信されます。この場合、どこに文書化されていますか?
私の2番目の理論は、bashはデフォルトでSIGQUIT
を無視する(つまり、no-opハンドラーを持っている)だけでなく(manページが示唆しているように)、トラップをまったく許可しないというものです。この理論は最初の理論と重複しています。これは、SIGQUIT
が親と子の両方に送信される可能性があるためですが、親(bash
)はそれをトラップできません。この場合、bashスクリプトでSIGQUIT
をトラップする方法はありますか?...おそらく設定できるshopt
がありますか?
編集:これは、bash4.1.5を実行しているgnome-terminal2.32.0のUbuntu10.10にあり、はい、^\
はSIGQUITを発行するように構成されています(stty -a
によって報告され、^\
SIGQUITをping
などの他のプログラムに発行することで確認されます)。
更新:
問題はどういうわけかgnome-terminalに起因しているに違いないことを発見しました。このスクリプトを仮想コンソールから実行すると(つまり、ctrl-alt-f1
を実行してXから抜け出す)、^\
を押すと、SIGQUITが完全にトラップされます。同じbashとすべてなので、唯一の違いはターミナルエミュレーターでなければなりません。だから今私の質問は次のようになります:この点で仮想コンソールのように動作するようにgnome-terminalを構成するにはどうすればよいですか?私は仮想コンソールとgnome-terminalでdiff
の出力をジェネラコディセタグコードしました。違いはありますが、すぐに関連するものは何もないようです(たとえば、両方にジェネラコディセタグコードがあります)。
更新2:
別の実験。 gnome-terminalでstty -a
を実行するだけです。 quit = ^\;
を押すと、信号がキャッチされなくなります。次に、仮想コンソールで$ sleep 60
を実行します。 ^\
を押すと、シグナルがキャッチされます。プロセスは$ sleep 60
を出力して終了します。しかし、今度はgnome-terminalで^\
を実行し、Quit
を押します。信号は期待どおりにキャッチされて処理されます。そのため、仮想コンソールから呼び出されたときに他のプログラムがSIGQUITをキャッチしたとしても、他のプログラムはSIGQUITをキャッチできないなど、gnome-terminalには奇妙なことがあります。おそらく、gnome-terminalをアップグレードする必要があります。
解決
これはgnome-terminal2.32.0のある種のバグであるとしか思えません。その後、gnome-terminal2.32.1(およびbash 4.2.8)を使用してUbuntu 11.04にアップグレードしましたが、SIGQUITは期待どおりにトラップされています。
他のヒント
XFCEを使用したFedora19でも同じ動作が見られます。ps s
によると、xfce4ターミナルのbashではSIGQUITが無視され、yes >/dev/null &
が実行され、ps s
は、サブプロセスでもSIGQUITが無視されていることを示しています。(同じ端末から)ssh localhost
を実行すると、sshセッションのシェルでもSIGQUITが無視されますが、yes >/dev/null &
では無視されません。
gnome-terminalについて言及している上記のコメントを考えると、バグは2つの端末の共通部分であるvte
ライブラリにあると思います。私のはvte-0.28.2-9.fc19.x86_64
です。