2009-04-22 11 views
6

respuestas permeables a estas preguntas se han centrado en las horquillas:¿Cómo puedo eliminar las llamadas al "sistema" de Perl cuando se mata la secuencia de comandos principal?

Para esta pregunta, sólo estoy preguntando acerca de las llamadas a la función de 'sistema' .

Decir que tengo un script llamado sleep.pl:

use strict; 
use warnings; 
sleep(300); 

que a continuación tienen una escritura llamada kill.pl

use strict; 
use warnings; 
system("sleep.pl"); 

corro kill.pl y usando ps encontrar el ID de proceso de kill.pl y matarlo (no usar kill -9, solo kill normal)

sleep.pl todavía está sleepi ng.

Imagino que la solución a mi pregunta implica un controlador SIG, pero ¿qué debo poner en el controlador para matar el proceso secundario?

+0

Esto necesita etiquetas adicionales. [matar] por ejemplo. –

Respuesta

3

Utilice setsid para hacer que su proceso sea el nuevo líder del grupo. Luego puedes enviar un kill al ID del grupo y matar a todos los procesos que pertenecen al grupo. Todos los procesos generados por el proceso de líder heredan la ID del grupo y pertenecen a su grupo recién creado. Así que enviar un asesinato al grupo los matará a todos. El único inconveniente es que para poder usar setsid debe cerrar su estándar de entrada y salida, ya que es un requisito para setsid.

3
use strict; 
use warnings; 
setpgrp $$, 0; 
system("sleep.pl"); 
END {kill 15, -$$} 

Pero si necesita este enfoque, haga algo mal. No deberías hacer esto. Ejecutar y matar a su proceso de matar de la manera correcta en su lugar.

$ perl -e 'system("sleep 100")' & 
[1] 11928 
$ ps f 
    PID TTY  STAT TIME COMMAND 
4564 pts/1 Ss  0:01 /bin/bash 
11928 pts/1 S  0:00 \_ perl -e system("sleep 100") 
11929 pts/1 S  0:00 | \_ sleep 100 
11936 pts/1 R+  0:00 \_ ps f 
$ kill %1 
[1]+ Terminated    perl -e 'system("sleep 100")' 
$ ps f 
    PID TTY  STAT TIME COMMAND 
4564 pts/1 Rs  0:01 /bin/bash 
11949 pts/1 R+  0:00 \_ ps f 

Cómo funciona? Shell (bash in mine case) debería establecer su proceso como líder de grupo si se ejecuta en segundo plano. Luego, si usa kill %?, el shell de sintaxis mata al grupo de la manera correcta. Compare esto:

$ perl -e 'system("sleep 100")' & 
[1] 12109 
$ ps f 
    PID TTY  STAT TIME COMMAND 
4564 pts/1 Rs  0:01 /bin/bash 
12109 pts/1 S  0:00 \_ perl -e system("sleep 100") 
12113 pts/1 S  0:00 | \_ sleep 100 
12114 pts/1 R+  0:00 \_ ps f 
$ kill 12109 
[1]+ Terminated    perl -e 'system("sleep 100")' 
$ ps f 
    PID TTY  STAT TIME COMMAND 
4564 pts/1 Ss  0:01 /bin/bash 
12124 pts/1 R+  0:00 \_ ps f 
12113 pts/1 S  0:00 sleep 100 

Pero kill %? funciona de esta manera:

$ perl -e 'system("sleep 100")' & 
[1] 12126 
$ ps f 
    PID TTY  STAT TIME COMMAND 
4564 pts/1 Rs  0:01 /bin/bash 
12126 pts/1 S  0:00 \_ perl -e system("sleep 100") 
12127 pts/1 S  0:00 | \_ sleep 100 
12128 pts/1 R+  0:00 \_ ps f 
$ kill -12126 
[1]+ Terminated    perl -e 'system("sleep 100")' 
$ ps f 
    PID TTY  STAT TIME COMMAND 
4564 pts/1 Ss  0:01 /bin/bash 
12130 pts/1 R+  0:00 \_ ps f 
+0

En resumen, use un PID negativo. –

2

Su pregunta realmente es una instancia específica de la más general "cómo asegurar un niño muere cuando el padre muere" cuestión. Simplemente no hay forma de evitar eso. No hay nada realmente especial sobre el sistema(); solo abre un proceso secundario y espera a que salga.

sistema() es más o menos esto:

sub system 
{ 
    my $kidpid = fork; 
    if ($kidpid) 
    { 
     waitpid $kidpid; 
      # parent process blocks here waiting for the child process to return 
    } 
    else 
    { 
     exec(@_); 
    } 
} 

matando al grupo de procesos se trata de la única opción.

Cuestiones relacionadas