tutorial sintaxis programacion guia ejemplos desde completo cero aprender perl ipc

programacion - sintaxis de perl



¿Cómo ejecuto un script Perl desde un script Perl? (9)

Tengo un script de Perl que necesita ejecutar otro script de Perl. Este segundo script se puede ejecutar directamente en la línea de comandos, pero necesito ejecutarlo desde mi primer programa. Tendré que pasarle algunos parámetros que normalmente se pasarían cuando se ejecute de manera independiente (el primer script se ejecuta periódicamente y ejecuta el segundo script bajo un cierto conjunto de condiciones del sistema).

Las búsquedas preliminares de Google sugieren el uso de patillas o una llamada al sistema (). ¿Hay otras formas de ejecutarlo? (Supongo que sí, ya que es Perl de quien estamos hablando: P) ¿Qué método es el preferido si necesito capturar la salida del programa invocado (y, si es posible, canalizar ese resultado mientras se ejecuta a stdout como si fuera el segundo programa fue invocado directamente)?

(Editar: oh, ahora SO sugiere algunas preguntas relacionadas. Esta es cercana, pero no exactamente igual a lo que estoy preguntando. El segundo programa probablemente demorará una hora o más en ejecutarse (muchas E / S), por lo que No estoy seguro de que una invocación excepcional sea la adecuada para esto).


Consulte la documentación perlipc para ver varias opciones de comunicación entre procesos.

Si su primer script simplemente configura el entorno para el segundo script, es posible que esté buscando un exec .


Puedes hacerlo .

{ local @ARGV = qw<param1 param2 param3>; do ''/home/buddy/myscript.pl''; }

Evita la sobrecarga de la carga en otra copia de Perl.


Puedo pensar en algunas maneras de hacer esto. Ya mencionaste los dos primeros, así que no entraré en detalles sobre ellos.

  1. backticks: $ retVal = `` perl somePerlScript.pl ;
  2. Llamada al sistema ()
  3. eval

La evaluación se puede llevar a cabo sorbiendo el otro archivo en una cadena (o una lista de cadenas), luego ''evaluando las cadenas. Aquí hay una muestra:

#!/usr/bin/perl open PERLFILE, "<somePerlScript.pl"; undef $/; # this allows me to slurp the file, ignoring newlines my $program = <PERLFILE>; eval $program;

4. hacer:

do ''somePerlScript.pl''


Quería hacer algo como esto para descargar no-subrutinas en un archivo externo para facilitar la edición. De hecho, hice esto en una subrutina. La ventaja de esta forma es que esas "mis" variables en el archivo externo se declaran en el espacio de nombres principal. Si usa ''do'', aparentemente no migran al espacio de nombres principal. Tenga en cuenta que la presentación a continuación no incluye el manejo de errores

sub getcode($) { my @list; my $filename = shift; open (INFILE, "< $filename"); @list = <INFILE>; close (INFILE); return /@list; } # and to use it: my $codelist = []; $codelist = getcode(''sourcefile.pl''); eval join ("", @$codelist);


Si necesita llamar asincrónicamente su script externo -sólo quiere iniciarlo y no esperar a que termine-, entonces:

# On Unix systems, either of these will execute and just carry-on # You can''t collect output that way `myscript.pl &`; system (''myscript.pl &''); # On Windows systems the equivalent would be `start myscript.pl`; system (''start myscript.pl''); # If you just want to execute another script and terminate the current one exec (''myscript.pl'');


Usa los trazos atrás si necesitas capturar la salida del comando.

Use el system si no necesita capturar la salida del comando.

TMTOWTDI: entonces hay otras formas también, pero esas son las dos más fáciles y más probables.


Ya has obtenido buenas respuestas a tu pregunta, pero siempre existe la posibilidad de adoptar un punto de vista diferente: tal vez deberías considerar refaccionar la secuencia de comandos que deseas ejecutar desde el primer guión. Convierta la funcionalidad en un módulo. Use el módulo del primer guión y del segundo guión.


La ubicación de su intérprete perl actual se puede encontrar en la variable especial $^X Esto es importante si Perl no está en su camino, o si tiene varias versiones de Perl disponibles, pero para asegurarse de que está utilizando la misma en todos los ámbitos.

Cuando se ejecutan comandos externos, incluidos otros programas de Perl, determinar si realmente se ejecutan puede ser bastante difícil. Inspeccionando $? puede dejar cicatrices mentales duraderas, entonces prefiero usar IPC::System::Simple (disponible desde el CPAN):

use strict; use warnings; use IPC::System::Simple qw(system capture); # Run a command, wait until it finishes, and make sure it works. # Output from this program goes directly to STDOUT, and it can take input # from your STDIN if required. system($^X, "yourscript.pl", @ARGS); # Run a command, wait until it finishes, and make sure it works. # The output of this command is captured into $results. my $results = capture($^X, "yourscript.pl", @ARGS);

En los dos ejemplos anteriores, los argumentos que desea pasar a su programa externo van a @ARGS . El shell también se evita en los dos ejemplos anteriores, lo que le da una pequeña ventaja de velocidad y evita cualquier interacción no deseada que involucre metacaracteres del shell. El código anterior también espera que su segundo programa devuelva un valor de salida cero para indicar el éxito; si ese no es el caso, puede especificar un primer argumento adicional de valores de salida permitidos:

# Both of these commands allow an exit value of 0, 1 or 2 to be considered # a successful execution of the command. system( [0,1,2], $^X, "yourscript.pl", @ARGS ); # OR capture( [0,1,2, $^X, "yourscript.pl", @ARGS );

Si tiene un proceso de larga ejecución y desea procesar sus datos mientras se está generando, entonces es probable que necesite un canal abierto o uno de los módulos IPC más pesados ​​del CPAN.

Habiendo dicho todo eso, cada vez que necesite llamar a otro programa Perl de Perl, puede considerar si el uso de un módulo sería una mejor opción. Iniciar otro programa conlleva bastantes gastos generales, tanto en términos de costos iniciales como de costos de E / S para mover datos entre procesos. También aumenta significativamente la dificultad de manejo de errores. Si puede convertir su programa externo en un módulo, puede encontrar que simplifica su diseño general.

Todo lo mejor,

Pablo


#!/usr/bin/perl use strict; open(OUTPUT, "date|") or die "Failed to create process: $!/n"; while (<OUTPUT>) { print; } close(OUTPUT); print "Process exited with value " . ($? >> 8) . "/n";

Esto iniciará la date del proceso y canalizará la salida del comando al identificador de archivo OUTPUT, que puede procesar una línea a la vez. Cuando el comando finaliza, puede cerrar el identificador de archivo de salida y recuperar el valor de retorno del proceso. Reemplaza la date con lo que quieras.