Inicie procesos en segundo plano en un grupo y luego elimínelos a todos

Inicie procesos en segundo plano en un grupo y luego elimínelos a todos

El otro día intenté escribir un guión que mataría a unPIDy todos sus procesos secundarios, pero después de dedicarle algún tiempo, decidí que no era confiable, porque a veces algunos de los niños terminaban con unPPIDde1.

Ahora, lo que estoy buscando es cómo puedo ejecutar la siguiente función en segundo plano y tener la función y curltodo en el mismogrupoy luego elimine este script si se atasca, eliminando todos los elementos secundarios que quedaron en segundo plano:

download(){
    until curl -s -S -L -A Mozilla/5.0 -m 300 "$@"; do
        echo Retrying in 5 seconds... >&2
        sleep 5
    done
}

for url in foo.com bar.com baz.com; do
    download $url >$url &
done
wait

Sé que no es necesaria esta función download, pero la incluí aquí porque es una función que uso muchas veces en este script. Además, estoy dando un límite de tiempo máximo de300a curl, pero dependiendo de algunos errores de red, también se atasca.

Respuesta1

Normalmente, si invoca su script desde un shell interactivo, se colocará en un nuevo grupo de procesos (también conocido como job), por lo que si está Ctrl-Cen él, todos los procesos iniciados por ese script recibirán un SIGINT.

Si también lo inició en segundo plano (aún desde un shell interactivo), también se iniciará en su propio grupo de procesos.

Puede obtener información sobre grupos de procesos con:

ps -j

( jes por job controllo cual es el comportamiento de los shells que ejecutan líneas de comando en grupos de procesos para poder administrarlos (primer plano/fondo/eliminar/suspender/reanudar)).

Puedes informarte sobre eltrabajosde su shell interactivo con el jobscomando (aunque no todos los procesos que contiene). jobs -ple mostrará la identificación del grupo de procesos.

Puede eliminar a los miembros de un grupo de procesos enviando una señal a -xdónde xestá la identificación del grupo de procesos (PGID) o utilizando especificaciones de trabajos con %job-number. Por ejemplo:

$ sleep 30 | sleep 40 &
[1] 6950 6951
$ ps -j
  PID  PGID   SID TTY          TIME CMD
 6031  6031  6031 pts/3    00:00:00 zsh
 6950  6950  6031 pts/3    00:00:00 sleep
 6951  6950  6031 pts/3    00:00:00 sleep
 6952  6952  6031 pts/3    00:00:00 ps
$ kill -- -6950
[1]  + terminated  sleep 30 | sleep 40
$ sleep 30 | sleep 40 &
[1] 6955 6957
$ jobs
[1]  + running    sleep 30 | sleep 40
$ kill %1
[1]  + terminated  sleep 30 | sleep 40

Ahora, si no se inicia desde un shell interactivo, su script terminará en el mismo grupo de procesos que su padre. Entonces, matar ese grupo de procesos podría terminar matando muchos otros procesos que no deseas matar.

Lo que podría hacer en su script es iniciar el grupo de procesos usted mismo.

Me gusta agregando:

[ "$(ps -o pgid= -p "$$")" -eq "$$" ] ||
  exec perl -e 'setpgrp or die "setpgrp; $!"; exec @ARGV' -- "$0" "$@"

(que vuelve a ejecutar el script después de haber llamado perlpara iniciar un nuevo grupo de procesos si detectamos que no somos un líder de grupo de procesos) al inicio de su script.

De esa manera, tiene la garantía de que el script se ejecutará en su propio grupo de procesos.

Sin embargo, lo que eso significa es que si lo haces:

something | myscript | something

En un shell interactivo, es probable que myscriptno sea el líder del grupo de proceso. Al hacer lo setpgrpanterior, el script ya no estará en el grupo de procesos de primer plano de la terminal, lo que significa Ctrl-Cque no lo eliminará.

información relacionada