2016-08-18 6 views
2

ジョブ制御をシェルスクリプトに有効にすると(set -mを使用)、プロセス信号を捕まえることができなくなりました。私は上記のコードを実行し、私は例えばはCtrl + Cを押すと、何も起こりませんジョブ制御がスクリプトで有効になっているときに、プロセス信号を取得できないのはなぜですか?

#!/bin/bash 

set -m 

for i in `seq 15`; do 
    trap 'echo " Signal $i catched"' $i 
done 

while true; do 
    echo " Waiting for a process signal" 
    sleep 999 
done 

Waiting for a process signal 
^CWaiting for a process signal 

をしかし、私はset -mを削除する同じコードを実行すると、次のコードを見てみましょう

Waiting for a process signal 
^C Signal 15 catched 

私の質問

は次のとおりです:

    、私は答えを得ますか
  1. なぜ機能しないのですか?
  2. ジョブ制御が有効なときにプロセス信号を捕捉することは可能ですか?

注:sleepの代わりにreadを使用すると、すべてのプロセスで発生するわけではありません。

+1

最初にスクリプトでジョブ制御を有効にするのはなぜですか? – Barmar

+1

ジョブ制御は、外部プログラムをシェルとは異なるプロセスグループで実行することによって機能します。キーボード信号はフォアグラウンドプロセスグループにのみ送られ、プログラムの実行中はシェルはフォアグラウンドグループには含まれません。 – Barmar

+0

@Barmar場合によっては、ジョブ制御はスクリプトで便利です。たとえば、私がバックグラウンドで新しいプロセスを開始するとき、将来、プロセスグループ全体を強制終了する必要があれば、私はそうすることができません。ジョブ制御が有効になっていない場合、新しいプロセスグループは作成されないため、作成されたすべてのプロセスは現在のグループに属します。 – Luisg123v

答えて

3

解決策は、スリープをバックグラウンドで行い、スリープが完了するまで待つためにbashビルトイン(wait)を使用することです。

#!/bin/bash 

set -m 

for i in `seq 15`; do 
    trap 'echo " Signal $i catched"' $i 
done 

while true; do 
    echo " Waiting for a process signal" 
    sleep 999 & wait $! 
done 

サンプル実行:詳細については

$ bash script 
Waiting for a process signal 
^C Signal 15 catched 
Waiting for a process signal 
^C Signal 15 catched 
Waiting for a process signal 

Greg's FAQを参照してくださいしたがって、これを試してみてください。

+1

このソリューションをさらに優れたものにするのは、完全に機能するだけでなく、呼び出されるプログラムでも機能するということです。なぜなら、どんなプログラムが呼び出されてもバックグラウンドに置かれ、すべての信号を捕まえる前景に「待ち」があるからです。 – Luisg123v

関連する問題