2010-10-13 5 views
5

J'ai essayé d'utiliser system() avec fork(), j'ai essayé exec(), et je n'ai toujours pas obtenu ce dont j'avais besoin.Comment puis-je exécuter une commande Windows externe et revenir instantanément en Perl?

Je veux écrire un script Perl qui exécute, disons, un script Perl différent 5 fois de suite (en lui envoyant différentes valeurs de paramètres), mais qu'il soit exécuté simultanément. Je me rends compte que je pouvais transformer mon script dans un fichier .pm et la référence, mais je préfère garder le script enfant système indépendant du parent ...

  • () fonctionne, mais exécute les commandes consécutivement (est logique par doc)
  • exec() ne fonctionne pas - il exécute la première méthode (sens par doc)
  • I a ajouté un script fork() à l'enfant perl puis essayé système à l'aide (
  • cela n'a pas fonctionné non plus.
  • commande backtick 'documents dit fonctionne comme système() ...

est pas là un moyen simple en Perl (im en utilisant Windows XP) pour exécuter un processus, et ne se soucient pas du retourner les valeurs ou antyhing et continuer juste sur la ligne suivante du script parent?

+1

un peu de code, afin que nous puissions voir ce qui ne fonctionne pas. – Ether

Répondre

8

Sous Windows, vous pouvez attribuer le drapeau super-secret 1 au système, IIRC.

system 1, @cmd; 

Une recherche rapide Google pour cette question sur PerlMonks donne: http://www.perlmonks.org/?node_id=639814

espoir qui aide.

+0

cela a fonctionné génial. Merci. Première utilisation de Perl, cela fonctionne très bien. merci à tous ceux qui ont répondu après mon commentaire – dferraro

+0

@dferraro => bienvenue dans la terre magique de Perl, j'espère que vous apprécierez votre séjour. En général, je recommanderais de rester à l'écart des solutions spécifiques au système d'exploitation si une solution plus générale existe. Vous ne savez jamais quand vous aurez besoin du script pour travailler sur une plate-forme imprévue. –

+0

merci pour l'accueil ... Je voudrais fuir comme un diable maintenant. Je n'ai toujours pas vu une seule ligne de perl qui ne m'a pas pris 5 minutes à surpasser;) – dferraro

2

Vous devez bifurquer dans le parent, puis exec dans le nouveau processus. Il va comme ceci, en supposant A est le script original, et B est celui que vous voulez faire 5 fois:

   A1 
fork in A1 -> A1 A2 
exec B in A2 -> A1 B2 
fork in A1 -> A1 A3 B2 
exec B in A3 -> A1 B3 B2 

etc.

+0

Comment puis-je bifurquer dans le parent? La fourchette ne prend pas de paramètres, donc Comment puis-je dire quelle commande exécuter ... – dferraro

+0

Vous appelez d'abord ['fork'] (http://perldoc.perl.org/functions/fork.html). Cela duplique le processus comme indiqué, puis 'fork 'renvoie deux fois. Vous utilisez ensuite la valeur de retour pour déterminer le processus dans lequel vous vous trouvez. Si ce n'est pas zéro, c'est le parent; si 0, alors l'enfant. Ensuite, dans l'enfant, vous appelez ['exec'] (http://perldoc.perl.org/functions/exec.html). Eric a fourni un exemple concis. –

12

vous pouvez le faire comme celui-ci (fourchette dans le parent, exec chez l'enfant):

for my $cmd qw(command1 command2 command3) { 
     exec $cmd unless fork 
} 

la façon dont exec $cmd unless fork fonctionne est que fork retourne une valeur réelle dans le parent (l'identifiant de processus) et renvoie une valeur fausse chez l'enfant, ainsi exec $cmd ne se fasse automatiquement si fork renvoie false (un ka, chez l'enfant).

ou si vous voulez garder un œil sur le processus car il fonctionne en même temps:

my @procs; 

for my $cmd qw(cmd1 cmd2 cmd3) { 

    open my $handle, '-|', $cmd or die $!; 

    push @procs, $handle; 
} 

alors vous pouvez lire à partir d'un élément de @procs si vous avez besoin.

Ou jetez un oeil à l'un des nombreux modules cpan comme Forks::Super qui gèrent les détails de la gestion des fourches.

+0

Sachez que fork() sur Windows a quelques complications, et puisque l'open est simplement une fourchette sous les couvertures, vous les verrez là aussi. – Tanktalus

2

Un module est trop lourd pour ce travail. Vous voulez fork pour créer un nouveau processus, puis exec pour exécuter une commande dans le nouveau processus.Pour exécuter cinq commandes, vous avez besoin de quelque chose comme:

for (my $i=0; $i<5; $i++) { 
    if (fork() == 0) { 
     exec($command[$i]); # runs command, doesn't return 
    } 
} 
+0

Un module n'est pas exagéré si vous voulez un comportement multiplateforme qui cache tout le comportement spécifique à la plate-forme que l'émulation fork sur Windows apporte . Cacher la complexité derrière une interface (espérons-le) simple est l'un des objectifs des modules. – Tanktalus

+1

Si vous avez la version 5.8 ou ultérieure, il n'y a rien de mal avec fork et exec sur Windows. –

3

Une approche très légère.

Windows:

foreach my $cmd (@cmds) 
{ 
    `start $cmd`; 
} 

Unix:

foreach my $cmd (@cmds) 
{ 
    `$cmd &`; 
} 
+0

J'ai essayé parce que ça paraissait simple, mais ça n'a pas ouvert les fenêtres de la console et ça s'est accroché à la dernière exécution ...? – dferraro

+0

En général, j'aime éviter les backticks juste pour éviter le shell. Surtout sur Windows où $ cmd peut contenir des espaces. – Tanktalus

Questions connexes