Comment puis-je attendre que Perl attende des processus enfants en arrière-plan avec system ()?

J’ai du code Perl qui exécute un script shell pour plusieurs parameters, pour simplifier, je suppose que j’ai un code qui ressemble à ceci:

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

Je voudrais faire encore plus de choses après cela, mais je ne peux pas trouver un moyen d’attendre que tous les processus enfants se terminent avant de continuer.

Convertir le code pour utiliser fork () serait difficile. N’y a-t-il pas un moyen plus facile?

Utiliser fork / exec / wait n’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"; 

Vous allez devoir changer quelque chose, changer le code pour utiliser fork est probablement plus simple, mais si vous ne voulez pas utiliser fork, vous pouvez utiliser un script shell wrapper qui touche un fichier quand il est fait et ensuite avoir votre code Perl vérifier l’existence des fichiers.

Voici le wrapper:

 #!/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 frappe 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; } 

La conversion en fork () peut être difficile, mais c’est le bon outil. system () est un appel bloquant; vous obtenez le comportement non-bloquant en exécutant un shell et en lui disant d’exécuter vos scripts en arrière-plan. Cela signifie que Perl n’a aucune idée de ce que pourraient être les PID des enfants, ce qui signifie que votre script ne sait pas quoi attendre.

Vous pouvez essayer de communiquer les PID au script Perl, mais cela devient rapidement incontrôlable. Utilisez fork ().