Pressionando Ctrl-C pára o script bash, mas não pare o script PHP chamado pelo script

3

Eu preciso executar alguns scripts a cada poucos minutos. A lógica foi feita em PHP e está funcionando muito bem. Para manter as coisas juntos, eu fiz 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.php tem um sono dentro dele porque só posso processá-lo a cada N minutos. Ele irá 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 + C neste momento, enquanto estiver dormindo, ele mata o script bash, mas não mata o php chamado roteiro. Eu entendo que há um processo diferente em execução.

Existe uma maneira de matar o script e todos os "filhos"? Ou devo ir com outra abordagem para executar esses scripts?

    
por Daniel Costa 29.09.2015 / 15:48

2 respostas

4

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

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

pkill -P $$

-P diz

-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
}

Como isso

kill_descendant_processes $$ true

Qual vai matar o processo atual e todos os descendentes. Você provavelmente vai querer chamar isso de um manipulador de armadilha. Ou seja, quando você pressionar ctrl + c , seu script será enviado SIGINT e você poderá capturar esse sinal e manipulá-lo. Por exemplo:

trap cleanup INT

cleanup() {
    kill_descendant_processes $$ true
}
    
por 29.09.2015 / 16:29
0

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
}
    
por 14.10.2015 / 09:53