2009-07-16 11 views
5

Tengo un modo de ejecución en mi aplicación web CGI::Application que me gustaría poder activar desde la línea de comandos para poder automatizarlo. Desde la perspectiva de la aplicación web, procesa algo y envía los resultados en un correo electrónico.¿Cómo puedo ejecutar un modo de ejecución CGI :: Application desde la línea de comandos?

cuando se llama desde la interfaz web que pasa en un conjunto de parámetros (dirección de correo electrónico, que consulta para ejecutar, fecha, etc) por lo que estos necesitan ser aprobada en.

¿Cómo puedo construir una llamada al CGI :: Aplicación de aplicación que será la misma que si la ejecutara desde la web?

Respuesta

3

Al profundizar en la documentación CGI::App y CGI, parecía ser más sencillo de lo que pensaba. El caso más simple (sin verdadera manipulación de argumento o hacer frente a la salida de la llamada carrera webapp) es:

#!/usr/bin/perl 

use strict; 
use warnings; 

use CGI; 
use WebApp; 

my $cgi = new CGI(\%{@ARGV}); 

my $webapp = WebApp->new(QUERY => $cgi); 
$webapp->run(); 

sólo se necesita una serie de pares de valores separados por espacios nombre para crear el CGI. Necesita pasar el modo de ejecución y todos los argumentos.

+1

Es incluso más fácil que eso; ver http://search.cpan.org/perldoc/CGI#DEBUGGING – ysth

+0

Es cierto que el formulario 'your_script.pl name1 = value1 name2 = value2' funciona para ejecutar el archivo CGI :: App .cgi básico, sin embargo, perdería cualquier capacidad para controlar la entrada, establecer los valores predeterminados, etc. –

+0

Este ejemplo todavía se imprimiría en STDOUT, incluidos los encabezados HTTP, que no es deseable. Además, no es necesario involucrar CGI.pm. Simplemente confunde las cosas cuando pasa y procesa los argumentos directamente desde la línea de comandos con una herramienta de procesamiento de argumentos estándar como Getopt :: Long. –

0

así:

$ perl yourscript.pl field1=value1 field2=value2 

biblioteca CGI de Perl se encarga de la magia para usted, y parece que CGI :: Application basa en CGI (a juzgar por su código de ejemplo).

+0

También deberá configurar varias variables de entorno para simular las cosas que el servidor web configuraría. CGI.pm busca esos para que sepa qué hacer. –

+0

@brian d foy: no a menos que su código por alguna razón dependa de esos; CGI.pm funciona bien sin ellos. – ysth

+0

@ysth: si este modo de ejecución tiene efectos secundarios, debería usar POST ya que no es una solicitud idempotente. En ese caso, debe agregar -debug a la importación de CGI.pm para permitir que esto funcione. Eso es un cambio en el código que también tiene efectos secundarios. Es mucho más fácil hacerlo como George dice. –

0

En lugar de tener que pasar por la aplicación CGI :: cada vez que desea hacer algo, aplique una correcta separation of concerns, tal vez usando una configuración MVC. Toda la funcionalidad debería existir fuera de la aplicación CGI :: ya que eso solo debería funcionar como un controlador. Una vez que separas esos bits, puedes escribir fácilmente otros controladores para otros métodos de entrada.

No escriba una aplicación web; escriba una aplicación que tenga una interfaz web. Cuando tenga eso, puede darle fácilmente a su aplicación otro tipo de interfaces.

+0

Estoy completamente de acuerdo, hay una biblioteca que hace el trabajo real generando el resultado y he tratado de limitar la cantidad de código en la porción 'Controlador' de CGI :: A hasta el punto donde está formateando. Es simplemente mi parte de "holgazanería" que piensa que podría usar la aplicación CGI :: para enviar el correo electrónico en lugar de escribir otro guión para llamar a la biblioteca. –

+0

Bueno, la pereza con una L mayúscula le permite realizar fácilmente otras tareas sin trabajo futuro: que la pereza no es evitar el trabajo, sino el trabajo inicial para ahorrar tiempo después. –

+0

(referencia obligatoria a YAGNI, aunque tiendo a operar en modo L capital la mayor parte del tiempo) – markh

6

El original CGI specification hace que sea más fácil ejecutar las cosas desde la línea de comandos y fue diseñado no como una interfaz específica HTTP sino como algo que podría manejar FTP y Gopher así como nuevos esquemas de URL de alto nivel. Sé lo que quería cuando ayudé a especificarlo.

La especificación a la que hice referencia debería darle todo lo que necesita, pero en su mayor parte es solo una colección de variables de entorno. Si ve una solicitud de:

http://some.server.com/some/path?a=b&c=d 

Las variables de entorno vienen a buscar de esta manera:

SERVER_PROTOCOL=http 
REQUEST_METHOD=GET 
HTTP_HOST=some.server.com 
SERVER_PORT=80 
PATH_INFO=/some/path 
QUERY_INFO=a=b&c=d 

Para invertir la polaridad de que en Perl sería algo como esto:

$ENV{'SERVER_PROTOCOL'} = 'http'; 
$ENV{'REQUEST_METHOD'} = 'GET'; 
$ENV{'SERVER_PORT'} = 80; 
$ENV{'PATH_INFO'} = '/some/path'; 
$ENV{'QUERY_INFO'} = 'a=b&c=d'; 
system("perl your-CGI-script.pl"); 

Las cosas se vuelven un poco más complicadas en el manejo de consultas POST y hay más variables de entorno posibles que pueden ser necesarias. Peor de los casos se puede enumerar a todos con un script CGI rápida algo como:

print "Content-Type: text/plain\r\n\r\n"; 
foreach (keys(%ENV)) 
{ 
    print "$_=$ENV{$_}\r\n"; 
} 

Ahora poner esto en el servidor web en lugar de la secuencia de comandos CGI y puedes encontrar el ambiente que se pasa en (y el entorno original, por lo que deberá realizar algunas llamadas de evaluación).

+0

Cuando hago eso, normalmente uso un ejecutivo. Sin embargo, no hay gran estruendo. –

+0

Genial, has ayudado a especificar CGI. :) –

0

Puede automatizar llamando a la aplicación web usando curl, wget o una secuencia de comandos GET de LWP con los parámetros adecuados. He usado un sistema similar para tareas guiadas por cron con una aplicación Catalyst.

que se ocupa de todas las variables de entorno para que ..

+0

Esta solución agrega un problema adicional para resolver: ahora debe asegurarse de que el URI del trabajo cron esté protegido, de modo que solo se pueda acceder desde el trabajo cron. –

3

yo soy el mantenedor de CGI :: Application, y hacer esto todo el tiempo-- tengo docenas de guiones cron construidas con CGI :: Aplicación porque es conveniente compartir la infraestructura con la aplicación.

El enfoque más simple es la siguiente:

# There is no browser to return results to. 
$ENV{CGI_APP_RETURN_ONLY} = 1; 

my $app = WebApp->new; 
$app->direct_run_mode_method; 

En ese ejemplo, que evite el flujo normal y llamar a un método directamente. Asegúrese de no necesitar ninguna de las acciones de "configuración" o "desmontaje" que se realizarán en ese caso.

Si solo tiene un modo de ejecución al que está llamando, también puede simplemente configurar el "modo_inicial" y ejecutar ejecutar(), por lo que el modo de ejecución predeterminado se llama por defecto.

Otra idea: puede usar un módulo como Getopt :: Long y pasar valores a través del hash PARAM a new(), o reemplazar completamente el proceso de selección de modo de ejecución. Aquí hay un ejemplo donde los indicadores de línea de comando se usan para determinar el modo de ejecución:

sub setup { 
    my $self = shift; 

    $self->start_mode('send_error_digests'); 
    $self->run_modes([qw/ 
     send_error_digests 
     help 
    /]); 

    my ($dry_run, $help); 
    GetOptions(
     'dry-run' => \$dry_run, 
     'help' => \$help 
    ); 

    $self->param('dry_run' => $dry_run); 

    $self->mode_param(sub { 
     return 'help' if $help; 
     return $self->start_mode(); 
    }); 
} 
Cuestiones relacionadas