Comment puis-je faire Perl attendre les processus enfants ont commencé en arrière-plan avec le système ()?
-
06-09-2019 - |
Question
J'ai un code Perl qui exécute un script shell pour plusieurs paramètres, pour simplifier, je vais supposer que j'ai le code qui ressemble à ceci:
for $p (@a){
system("/path/to/file.sh $p&");
}
Je voudrais faire quelques plus de choses après cela, mais je ne peux pas trouver un moyen d'attendre que tous les processus enfants pour terminer avant de poursuivre.
Conversion du code à utiliser fork () serait difficile. N'y at-il un moyen plus facile?
La solution
En utilisant fork / exec / attente est pas si mal:
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";
Autres conseils
Vous allez devoir changer quelque chose, de changer le code à utiliser la fourchette est probablement plus simple, mais si vous êtes absolument contre l'utilisation de fourche, vous pouvez utiliser un script shell wrapper qui touche un fichier lorsqu'il est fait et alors votre chèque de code Perl pour l'existence des fichiers.
Voici l'emballage:
#!/bin/bash
$*
touch /tmp/$2.$PPID
Votre code Perl ressemblerait à ceci:
for my $p (@a){
system("/path/to/wrapper.sh /path/to/file.sh $p &");
}
while (@a) {
delete $a[0] if -f "/tmp/$a[0].$$";
}
Mais je pense que le code de fork est plus sûr et plus clair:
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;
}
Conversion à la fourchette () peut être difficile, mais il est l'outil approprié. system () est un appel de blocage; vous obtenez le comportement non-bloquant en exécutant une coquille et lui disant d'exécuter vos scripts en arrière-plan. Cela signifie que Perl n'a aucune idée de ce que les enfants des PIDs pourraient être, ce qui signifie que votre script ne sait pas quoi attendre.
Vous pouvez essayer de communiquer jusqu'à l'PIDs le script Perl, mais qui devient rapidement la main. Utiliser fork ().