Как я могу заставить Perl ждать дочерние процессы, запущенные в фоновом режиме с помощью system()?

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

Вопрос

У меня есть некоторый Perl-код, который выполняет сценарий оболочки для нескольких параметров, для упрощения я просто предположу, что у меня есть код, который выглядит следующим образом:

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

После этого я хотел бы сделать еще кое-что, но я не могу найти способ дождаться завершения всех дочерних процессов, прежде чем продолжить.

Преобразование кода для использования fork() было бы затруднительным.Разве нет более простого способа?

Это было полезно?

Решение

Использование fork / exec / wait не так уж плохо:

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

Другие советы

Вам придется что-то изменить, изменить код для использования fork, вероятно, проще, но если вы категорически против использования fork, вы могли бы использовать сценарий оболочки-оболочки, который прикасается к файлу, когда это делается, а затем ваш Perl-код проверяет существование файлов.

Вот обертка:

#!/bin/bash

$*

touch /tmp/$2.$PPID

Ваш Perl-код будет выглядеть следующим образом:

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

Но я думаю, что код разветвления безопаснее и понятнее:

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

Преобразование в fork() может быть сложным, но это правильный инструмент.system() - это блокирующий вызов;вы получаете неблокирующее поведение, выполняя оболочку и указывая ей запускать ваши скрипты в фоновом режиме.Это означает, что Perl понятия не имеет, какими могут быть PID дочерних элементов, а это значит, что ваш скрипт не знает, чего ждать.

Вы могли бы попытаться передать PID-коды скрипту Perl, но это быстро выходит из-под контроля.Используйте fork().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top