Нажатие 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
}

Связанный контент