按 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 - 如何殺死 shell 的所有子進程? - 堆疊溢位

如果你只關心殺死直接孩子,你應該可以做到

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
}

相關內容