2010-10-13 22 views
5

He intentado usar system() con fork(), intenté ejecutar(), y todavía no obtengo lo que necesito.¿Cómo puedo ejecutar un comando externo de Windows y regresar instantáneamente en Perl?

Quiero escribir un script Perl que ejecute, digamos, un script Perl diferente 5 veces seguidas (enviándole valores de parámetros diferentes), pero que se ejecute al mismo tiempo. Me di cuenta de que podía volver la secuencia de comandos en un archivo .pm y hacer referencia a ella, pero preferiría mantener el guión niño independiente de la matriz ...

  • sistema() funciona, pero ejecuta los comandos consecutivamente (tiene sentido por doc)
  • exec() no funciona - que sólo se ejecuta el primer método (tiene sentido por doc)
  • he añadido un tenedor() a la script de perl niño y luego trató de usar el sistema ()
  • Esto tampoco funcionó.
  • backtick documentos comando 'dice que funciona igual que el sistema() ...

¿No hay una manera simple en Perl (im utilizando Windows XP) para ejecutar un proceso, y no se preocupan por la devolver valores o antyhing y simplemente continuar en la siguiente línea del script padre

+1

Publicar un cierto código, para que podamos ver lo que no funcionó. – Ether

Respuesta

8

En Windows, puede dar la bandera súper secreta 1 al sistema, IIRC.

system 1, @cmd; 

Una rápida búsqueda en Google para esta pregunta en perlmonks da: http://www.perlmonks.org/?node_id=639814

Espero que ayude.

+0

esto funcionó increíble. Gracias. La primera vez que usas Perl, esto funciona muy bien. gracias a todos los que respondieron después de mi comentario – dferraro

+0

@dferraro => bienvenidos a la tierra mágica de Perl, espero que disfruten de su estancia. En general, recomendaría que se mantenga alejado de las soluciones específicas del sistema operativo si existe una solución más general. Nunca se sabe cuándo necesitará el script para trabajar en una plataforma imprevista. –

+0

gracias por la bienvenida ... Me gustaría huir como el infierno ahora. Todavía no he visto una sola línea de perl que no me haya tomado 5 minutos para soportarla;) – dferraro

2

Tiene que tenedor en el padre, luego ejecutar en el nuevo proceso. Dice así, suponiendo que A es el guión original, y B es el que usted quiere hacer 5 veces:

   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

¿Cómo puedo tenedor en el padre? fork no toma params, así que ¿cómo puedo decirle qué comando ejecutar ... – dferraro

+0

Primero llama ['fork'] (http://perldoc.perl.org/functions/fork.html). Eso duplica el proceso como se muestra, luego 'tenedor 'regresa dos veces. A continuación, usa el valor de retorno para determinar en qué proceso se encuentra. Si no es cero, es el padre; si 0, entonces el niño. Luego, en el niño, llama a ['exec'] (http://perldoc.perl.org/functions/exec.html). Eric proporcionó un ejemplo conciso. –

12

puede hacerlo de esta manera (tenedor en el padre, ejecutivo en el niño):

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

la forma en que exec $cmd unless fork funciona es que fork devolverá un valor real en el padre (el proceso de identificación) y devolverá un valor falso en el niño, por lo tanto exec $cmd solamente se ejecute si fork devuelve falso (a ka, en el niño).

o si desea llevar un control sobre el proceso ya que se ejecuta simultáneamente:

my @procs; 

for my $cmd qw(cmd1 cmd2 cmd3) { 

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

    push @procs, $handle; 
} 

entonces se puede leer de un elemento de @procs si es necesario.

O eche un vistazo a uno de los muchos módulos de cpan como Forks::Super que manejan los detalles de la administración de horquillas.

+0

Solo tenga en cuenta que la horquilla() en Windows tiene algunas complicaciones, y dado que la apertura es simplemente una horquilla bajo las sábanas, también las verá allí. – Tanktalus

2

Un módulo es excesivo para este trabajo. Desea fork para crear un nuevo proceso y luego exec para ejecutar un comando en el nuevo proceso.Para ejecutar cinco comandos, necesita algo como:

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

Un módulo no es exagerado si desea un comportamiento multiplataforma que oculte todo el comportamiento específico de la plataforma que la emulación de bifurcación en Windows trae . Ocultar la complejidad detrás de una interfaz (con suerte) simple es uno de los propósitos de los módulos. – Tanktalus

+1

Si tiene la versión 5.8 o posterior, no hay nada de malo en fork y exec en Windows. –

3

Un enfoque muy ligero.

de Windows:

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

Unix:

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

Lo intenté porque también parecía simple, pero no abrió ninguna ventana de consola y luego se colgó en la última ejecución ...? – dferraro

+0

En general, me gusta evitar backticks solo para evitar el shell. Especialmente en Windows donde $ cmd puede tener espacios. – Tanktalus

Cuestiones relacionadas