¿Cómo puedo hacer Perl esperar a que los procesos hijo se inició en el fondo con el sistema ()?

StackOverflow https://stackoverflow.com/questions/911520

Pregunta

Tengo algo de código Perl que ejecuta un script de shell para múltiples parámetros, para simplificar, sólo voy a asumir que tengo código que se parece a esto:

for $p (@a){
    system("/path/to/file.sh $p&");
}

Me gustaría hacer algunas cosas más después de eso, pero no puedo encontrar una manera de esperar a que todos los procesos hijo termine antes de continuar.

Convertir el código usar tenedor () sería difícil. ¿No hay una manera más fácil?

¿Fue útil?

Solución

El uso de tenedor / exec / espera no es tan malo:

my @a = (1, 2, 3);
for my $p (@a) {
   my $pid = fork();
   if ($pid == -1) {
       die;
   } elsif ($pid == 0) {
      exec '/bin/sleep', $p or die;
   }
}
while (wait() != -1) {}
print "Done\n";

Otros consejos

Usted va a tener que cambiar algo, cambiar el código para utilizar tenedor es probablemente más fácil, pero si usted está totalmente en contra de usar tenedor, se puede utilizar un script envoltorio que toca un archivo cuando se hace y luego tener su cheque de código Perl para la existencia de los archivos.

Aquí es el envoltorio:

#!/bin/bash

$*

touch /tmp/$2.$PPID

Su código de Perl se vería así:

for my $p (@a){
    system("/path/to/wrapper.sh /path/to/file.sh $p &");
}
while (@a) {
    delete $a[0] if -f "/tmp/$a[0].$$";
}

Sin embargo, creo que el código de bifurcación es más seguro y más claro:

my @pids;
for my $p (@a) {
    die "could not fork" unless defined(my $pid = fork);\
    unless ($pid) { #child execs
        exec "/path/to/file.sh", $p;
        die "exec of file.sh failed";
    }
    push @pids, $pid; #parent stores children's pids
}

#wait for all children to finish
for my $pid (@pids) {
    waitpid $pid, 0;
}

La conversión a tenedor () podría ser difícil, pero es la herramienta correcta. system () es una llamada de bloqueo; que está recibiendo el comportamiento de no bloqueo mediante la ejecución de una concha y diciéndole que se ejecute las secuencias de comandos en el fondo. Eso significa que Perl tiene ni idea de lo que los PIDs de los niños podrían ser, lo que significa que su guión no sabía qué esperar.

Se podría tratar de comunicar los PID hasta el script de Perl, pero que pronto se le va de las manos. Utilice tenedor ().

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top