Al presionar Ctrl-C se detiene el script bash, pero no se detiene el script PHP llamado por el script.

Al presionar Ctrl-C se detiene el script bash, pero no se detiene el script PHP llamado por el script.

Necesito ejecutar algunos scripts cada pocos minutos. La lógica se creó en PHP y está funcionando muy bien. Para mantener las cosas juntas, he creado el siguiente script bash, que también funciona bien.

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

El script capturaRelatorio.phptiene un modo de suspensión porque solo puedo procesarlo cada N minutos. Imprimirá un mensaje diciendo que está durmiendo durante S segundos para que pueda monitorearlo.

Si llamo al script bash y presiono Ctrl+ Cen este momento, mientras está inactivo, mata el script bash, pero no mata el script php llamado. Entiendo que hay un proceso diferente ejecutándolo.

Entonces, ¿hay alguna manera de eliminar el script bash y todos los "niño"? ¿O debería optar por otro enfoque para ejecutar estos scripts?

Respuesta1

De esta respuesta:bash - ¿Cómo eliminar todos los subprocesos de Shell? - Desbordamiento de pila.

Si sólo te importa matar niños directos, deberías poder hacerlo.

pkill -P $$

-Pdice

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

Y $$significa el PID del proceso actual.

Si necesita eliminar procesos secundarios y cualquier proceso que puedan iniciar (nietos, etc.), debería poder usar la función que se encuentra en una respuesta diferente a esa pregunta:

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 esto

kill_descendant_processes $$ true

Lo que matará el proceso actual y todos los descendientes. Probablemente querrás llamar a esto desde un controlador de trampas. Es decir, cuando presione ctrl+ c, se enviará su script SIGINTy podrá captar esa señal y manejarla. Por ejemplo:

trap cleanup INT

cleanup() {
    kill_descendant_processes $$ true
}

Respuesta2

Puede actualizar el script bash para capturar 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
}

información relacionada