echo
またはSIGSTOP
信号を受信するとSIGHUP
が実行されるスクリプトがあるとします。
$cat test.sh
function clean_up {
echo "cleaning up!"
}
echo 'starting!'
trap clean_up SIGSTOP SIGHUP
sleep 100
私はそれをバックグラウンドで実行しました:
$./test.sh > output &
[4] 42624
次に、-1
、つまり [〜#〜] sighup [〜#〜] で殺しました
$kill -1 42624
しかし、trap
は期待どおりに機能しませんでした。つまり、output
ファイルの内容にcleaning up!
が含まれていません。
$cat output
starting!
どうした?
実際には印刷されましたが、結果を表示するには100秒待つ必要があります。
あなたが言った:
_$./test.sh > output &
[4] 42624
_
_ps aux
_をチェックすると、次のような結果が得られます。
_xiaobai 42624 0.0 0.1 118788 5492 pts/3 S 04:07 0:00 /bin/bash
xiaobai 42626 0.0 0.0 108192 668 pts/3 S 04:07 0:00 sleep 100
_
/ bin/bashのメインスクリプトプロセス、PID42624はまだスリープ100の終了を待っています。メインプロセスでもシグナル1を受信しましたが、最初に_sleep 100
_が完了するのを待たなければなりません。その後、タスクを実行する番です(つまり、_echo "cleaning up!"
_)。
スリーププロセスをバックグラウンドプロセスにすることができます。この場合、スクリプトプロセスは、スクリプトプロセスがまだ終了していない場合に限り、_echo "cleaning up!"
_を待たずに_sleep process
_を実行できます。
このスクリプトを使用して、概念(つまり、スクリプトがシグナルを処理する前にsleep
を待機している)を証明できます。
_function clean_up {
echo "cleaning up!"
}
echo 'starting!'
trap clean_up SIGHUP
sleep 5000 &
echo 1
sleep 20
echo 2
sleep 10
echo 3
_
このスクリプトを通常どおり_./test.sh > output
_で実行し、次に_ps aux
_を使用して_/bin/bash
_ PIDが23311であることを確認し、次に_kill -1 23311
_を実行します。同時に_cat output
_がステージを知るために、つまり、スクリプトがエコー1の後に_sleep 20
_に入ると、_kill -1 23311
_を送信し、2が出るのを待ちます。 2の前に一緒に印刷されました。最後に、_echo 3
_とスクリプトの終了です。
_$ cat output
starting!
1
cleaning up!
2
3
$
_
上記の実験により、スクリプトはシグナルSIGHUPを受信し、前のすべてのフォアグラウンドプロセスが完了した後、バックグラウンドプロセスを待たずに、シグナルハンドラーを実行することが証明されました。
元のスクリプトを使用して、ストーリーが面白くなります。_kill -1 PID_of_sleep_100
_を実行するとどうなりますか?
スリーププロセスはSIGHUPをスクリプトプロセスに返さないため、印刷せずにすべてのプロセスを終了します。
したがって、タスクの解決策があります。_kill -1 PPID
_(スクリプトプロセス)を実行して、SIGHUPをスクリプトプロセスに承認し、次に_kill -1 PID
_(スリーププロセス)を実行できます。スクリプトプロセスは終了する前にSIGHUPハンドラーを実行します。ハッキングを楽しんでください:)
すべての信号が同じというわけではありません。 SIGKILLはトラップを許可していません 。スクリプトプロセスを-9で強制終了すると、スリーププロセスは引き続き実行され、その親PIDは1になります(_ps -ef
_で確認)。
[更新] :
通常、信号Nがスクリプトにトラップされない場合、_kill -N script_PID
_はスクリプトを直接強制終了します。ただし、SIGINTに注意してください。スクリプトがトラップしなくても、_kill -2 script_PID
_は直接強制終了しません。スクリプトは、子プロセス(たとえば、sleep 10)が完了するまで待機します。ここで、script_PIDで複数のkill、つまり_kill -2 script_PID
_ AND _kill -user-defined_trap_N script_PID
_を実行すると仮定すると、次のようになります。
Bashがコマンドの完了を待機していて、トラップが設定されている信号を受信した場合、コマンドが完了するまでトラップは実行されません。
あなたの例では、trap
はsleep 100
が完了するまで実行されません。