Как я могу заставить Perl ждать дочерних процессов, запущенных в фоновом режиме с помощью system()?
У меня есть код Perl, который запускает оболочку script для нескольких параметров, чтобы упростить, я просто предполагаю, что у меня есть код, который выглядит так:
for $p (@a){
system("/path/to/file.sh $p&");
}
Я хотел бы сделать еще несколько вещей после этого, но я не могу найти способ дождаться завершения всех дочерних процессов, прежде чем продолжить.
Преобразование кода для использования fork() будет затруднительным. Нет ли более простого способа?
Ответы
Ответ 1
Использование 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";
Ответ 2
Вам нужно что-то изменить, изменение кода на использование вилки, вероятно, проще, но если вы настроены против использования fork, вы можете использовать оболочку оболочки script, которая касается файла, когда это будет сделано, и то проверьте свой код 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].$$";
}
Но я думаю, что код forking более безопасный и понятный:
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 pids
}
#wait for all children to finish
for my $pid (@pids) {
waitpid $pid, 0;
}
Ответ 3
Преобразование в fork() может быть трудным, но это правильный инструмент. system() - блокирующий вызов; вы получаете неблокирующее поведение, выполняя оболочку и сообщая ей, чтобы запустить ваши сценарии в фоновом режиме. Это означает, что Perl не знает, что такое PID от детей, а значит, ваш script не знает, чего ждать.
Вы можете попытаться передать PID до Perl script, но это быстро выходит из-под контроля. Используйте fork().