Pergunta

Eu tenho algum código Perl que executa um script shell para vários parâmetros, para simplificar, eu só vou assumir que eu tenho o código que se parece com isso:

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

Eu gostaria de fazer mais algumas coisas depois disso, mas não consigo encontrar uma maneira de esperar para que todos os processos filhos para terminar antes de continuar.

Convertendo o código para uso fork () seria difícil. não existe uma maneira mais fácil?

Foi útil?

Solução

Usando fork / exec / espera não é tão ruim:

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";

Outras dicas

Você vai ter que mudar alguma coisa, mudar o código para usar garfo é provavelmente mais simples, mas se você está morto conjunto contra o uso de garfo, você poderia usar um shell script wrapper que toca um arquivo quando ele é feito e depois ter seu cheque código Perl para a existência dos arquivos.

Aqui está a capa:

#!/bin/bash

$*

touch /tmp/$2.$PPID

Seu código Perl seria parecido com:

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

Mas eu acho que o código bifurcação é mais seguro e mais clara:

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

A conversão para fork () pode ser difícil, mas é a ferramenta correta. sistema () é uma chamada de bloqueio; você está recebendo o comportamento non-blocking executando um shell e dizendo-lhe para executar seus scripts em segundo plano. Isso significa que Perl tem idéia do que os PIDs dos filhos pode ser, o que significa que seu script não sabe o que esperar.

Você poderia tentar comunicar os PIDs até o script Perl, mas que rapidamente fica fora de mão. Use fork ().

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top