web-dev-qa-db-ja.com

SIGTSTP、SIGTTIN、およびSIGTTOUの「トラップコマンド」を書き換えることはできません。

SIGTSTP信号をトラップしたいのですが、トラップできません。引数なしでtrapコマンドだけを呼び出すと、次のようになります。

trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU

明らかに、私のtrapにはすでに事前定義された動作がいくつかあります。問題は、rootとしてログに記録されていても、書き換えることができないことです。 trapコマンドを使用すると、これら3つの信号では単に無視されます。それ以外の場合は正常に動作します。

次のように、コマンドだけで書き直そうとしました。

trap -- 'echo SIGTSTP' SIGTSTP

もう1つの奇妙なことは、この信号を使用でき、正常に機能していることです。無視されません。 SIGTSTPを使用して、他のプロセスの動作を停止し、SIGCONTを再度続行することができます。

それで、あなたはそれらのコマンドを書き直す方法を知っていますか?そして、この奇妙な行動を少し説明していただけませんか?


私のOSはLubuntu15.04で、GNU bash、バージョン4.3.30(1)-リリース(x86_64-pc-linux-gnu)を使用しています。

3
Eenoku

Ubuntu 15.04のbashを使用すると、期待どおりに機能するようです...スクリプトをどのように記述しますか?

#!/bin/bash
set -e
trap 'echo TSTP' TSTP
trap 'echo TTIN' TTIN
trap 'echo TTOU' TTOU
trap
while :; do read a; done # wait forever

サンプルセッション(3回入力) Ctrl+Z その後 Ctrl+C):

$ ./signal.sh
trap -- 'echo TSTP' SIGTSTP
trap -- 'echo TTIN' SIGTTIN
trap -- 'echo TTOU' SIGTTOU
^ZTSTP
^ZTSTP
^ZTSTP
^C

マニュアルで bashがインタラクティブで、ジョブ制御が有効になっている場合、これらの信号を無視することがわかりました。

  1. ジョブ制御(ジョブ制御を参照)はデフォルトで有効になっています。ジョブ制御が有効な場合、Bashはキーボードで生成されたジョブ制御信号SIGTTIN、SIGTTOU、およびSIGTSTPを無視します。

set +mでジョブcotnrolを無効にできます。ただし、bashではインタラクティブモードでハンドラーを更新することはできません。

$ bash -c trap
$ bash -c 'trap true TSTP && trap'
trap -- 'true' SIGTSTP
$ bash -i -c trap
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
$ bash -i -c 'trap true TSTP && trap'
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
$ bash -i -c 'set +m && trap true TSTP && trap'
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
2
yaegashi

使用しているシェルについて言及していなかったため、これがシェルのバグである場合、支援する方法はありません。

Bourne Shellのmanページを見る: http://schillix.sourceforge.net/man/man1/bosh.1.html 次のテキストが表示されます。

     bolic  names. Any attempt to set a trap on a signal that
     was ignored on entry to the current  Shell  is  ineffec-
     tive.  An  attempt  to  trap on signal 11 (memory fault)
     produces an error.code here

したがって、すべて問題ないかもしれませんが、これらの信号を無視してシェルが呼び出されました。

最新のOSを使用している場合は、

 `psig $$`

現在のシェルのシグナル処理を取得し、$$を他のプロセスIDに置き換えて、他のプロセスをチェックすることができます。

0
schily