BashスクリプトでSIGHUPが表示されませんか?


11

次のスクリプトがあります。

#!/bin/bash
echo "We are $$"
trap "echo HUP" SIGHUP
cat    # wait indefinitely

SIGHUP(を使用してkill -HUP pid)送信しても何も起こりません。

スクリプトを少し変更すると:

#!/bin/bash
echo "We are $$"
trap "kill -- -$BASHPID" EXIT    # add this
trap "echo HUP" SIGHUP
cat    # wait indefinitely

...スクリプトがecho HUP終了すると、(Ctrl + Cを押すと)スクリプトが正しく動作します。

roger@roger-pc:~ $ ./hupper.sh 
We are 6233
^CHUP

どうしたの?SIGHUPこのスクリプトに信号を送信するにはどうすればよいですか(必ずしもそうである必要はありません)。


4
シグナルが配信され、catプロセスが終了するとシグナルハンドラが実行されます。元のスクリプトを試し、を押しCtrl+Dcatプロセスを終了します。一方でcat、プロセスがフォアグラウンドである、HUP信号が作用されていません。(シェル組み込み)にcat置き換えて再試行してくださいread
Kusalananda

完璧です。誰かがそれを答えに変えたいと思っていますか?
Roger Lipscombe 2017

私はそれがそのように機能することを知っていますが、私よりも理由と理由を私よりも洞察力のある人に答えさせます。
Kusalananda

while true; do read; done最後に使用しました。それ以外の場合、テキストを入力するとテキストも終了します。Ctrl+ Cで終了します。
Roger Lipscombe 2017

回答:


21

Bashマニュアルには次のように記載されています。

bashがコマンドの完了を待機していて、トラップが設定されたシグナルを受信した場合、コマンドが完了するまでトラップは実行されません。

つまりbash、送信時にシグナルが受信されても​​、SIGHUPのトラップはcat終了時にのみ呼び出されます。

この動作が望ましくない場合は、bashビルトインを使用するか(例:read+のprintf代わりにループでcat)、またはバックグラウンドジョブを使用します(Stéphaneの回答を参照)。


9

@xhienneは既に理由を説明していますが、信号をすぐに(スクリプトを終了せずに)動作させたい場合は、コードを次のように変更できます。

#! /bin/bash -
interrupted=true
trap 'interrupted=true; echo HUP' HUP

{ cat <&3 3<&- & pid=$!; } 3<&0

while
  wait "$pid"
  ret=$?
  "$interrupted"
do
  interrupted=false
done
exit "$ret"

ファイル記述子の小さな踊りは、bashstdinを/dev/nullバックグラウンドで起動されたコマンドにリダイレクトするという事実を回避することです。


コードブロックがサブシェルで実行されるため、これは機能しますか?
Pysis 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.