Ctrl-C を押すと bash スクリプトは停止しますが、スクリプトによって呼び出される PHP スクリプトは停止しません。

Ctrl-C を押すと bash スクリプトは停止しますが、スクリプトによって呼び出される PHP スクリプトは停止しません。

数分ごとにいくつかのスクリプトを実行する必要があります。ロジックは PHP で作成されており、問題なく動作しています。まとめるために、以下の bash スクリプトを作成しましたが、これも問題なく動作します。

#!/bin/bash

calculaDiff() {
    DIFF=0

    while [ "$DIFF" -eq "0" ]; do
        DIFF=`php calculaDiff.php`
    done;
}

# need to calculate pending diffs
calculaDiff

# main loop
while true; do
    CAPTURA=`php capturaRelatorio.php`
    if [ "$CAPTURA" -eq "0" ]; then
        calculaDiff
    fi

    VERIFICA=`php verificaLimites.php`

done

スクリプトcapturaRelatorio.phpにはスリープが含まれています。これは、N 分ごとにしか処理できないためです。監視できるように、S 秒間スリープしていることを示すメッセージが出力されます。

このとき、 bash スクリプトを呼び出してCtrl+を押すとC、スリープ中に bash スクリプトは強制終了されますが、呼び出された php スクリプトは強制終了されません。別のプロセスが実行されていることは理解しています。

では、bash スクリプトとすべての「子」を強制終了する方法はありますか? それとも、これらのスクリプトを実行するために別の方法を採用する必要がありますか?

答え1

この回答から:bash - シェルのすべてのサブプロセスを強制終了するにはどうすればいいですか? - Stack Overflow

直系の子供を殺すことだけを気にするなら、

pkill -P $$

-P言う

-P, --parent ppid,...
      Only match processes whose parent process ID is listed.

そして、$$現在のプロセスの PID を意味します。

子プロセスと、それによって開始される可能性のあるプロセス (孫など) を終了する必要がある場合は、その質問に対する別の回答にある関数を使用できるはずです。

kill_descendant_processes() {
    local pid="$1"
    local and_self="${2:-false}"
    if children="$(pgrep -P "$pid")"; then
        for child in $children; do
            kill_descendant_processes "$child" true
        done
    fi
    if [[ "$and_self" == true ]]; then
        kill "$pid"
    fi
}

このような

kill_descendant_processes $$ true

これにより、現在のプロセスとすべての子孫が強制終了されます。おそらく、これをトラップ ハンドラーから呼び出す必要があるでしょう。つまり、ctrl+ を押すとcスクリプトが送信されSIGINT、そのシグナルをキャッチして処理できます。例:

trap cleanup INT

cleanup() {
    kill_descendant_processes $$ true
}

答え2

bash スクリプトを更新して、ctrl+c をトラップできます。

trap control_c SIGINT

function control_c() {
    echo "## Trapped CTRL-C"
    ps -ef | grep php | grep -v grep | awk '{ print $2 }' > php.kill
    for i in $(cat php.kill)
    do
        kill -9 $i > /dev/null
    done
    rm php.kill
}

関連情報