Pressionar Ctrl-C interrompe o script bash, mas não interrompe o script PHP chamado pelo script

Pressionar Ctrl-C interrompe o script bash, mas não interrompe o script PHP chamado pelo script

Preciso executar alguns scripts a cada poucos minutos. A lógica foi feita em PHP e está funcionando muito bem. Para manter tudo sob controle, criei o script bash abaixo, que também funciona bem.

#!/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

O script capturaRelatorio.phpestá suspenso porque só consigo processá-lo a cada N minutos. Ele imprimirá uma mensagem dizendo que está dormindo por S segundos para que eu possa monitorá-lo.

Se eu chamar o script bash e pressionar Ctrl+ Cneste momento, enquanto ele está dormindo, ele mata o script bash, mas não mata o script php chamado. Entendo que há um processo diferente executando-o.

Então, existe uma maneira de matar o script bash e todas as “crianças”? Ou devo adotar outra abordagem para executar esses scripts?

Responder1

Desta resposta:bash - Como matar todos os subprocessos do shell? - Estouro de pilha.

Se você só se preocupa em matar crianças diretas, você deveria ser capaz de fazer

pkill -P $$

-Pdiz

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

E $$significa o PID do processo atual.

Se você precisar eliminar processos filhos e quaisquer processos que eles possam iniciar (netos e assim por diante), você poderá usar a função que está em uma resposta diferente para essa pergunta:

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
}

Assim

kill_descendant_processes $$ true

O que matará o processo atual e todos os descendentes. Você provavelmente desejará chamar isso de um manipulador de trap. Ou seja, ao pressionar ctrl+ c, seu script será enviado SIGINTe você poderá captar esse sinal e tratá-lo. Por exemplo:

trap cleanup INT

cleanup() {
    kill_descendant_processes $$ true
}

Responder2

Você pode atualizar o script bash para interceptar 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
}

informação relacionada