如何从命令行运行CGI :: Application运行模式?

问题描述:

我在我的CGI::Application网络应用程序中有一个运行模式,我希望能够从命令行触发,这样我就可以实现自动化。从网络应用程序的角度来看,它会进行一些处理,然后通过电子邮件发送结果。如何从命令行运行CGI :: Application运行模式?

当从它通过一组参数(电子邮件地址,查询运行,日期等),网络接口调用,所以这些都需要在传递。

我如何构建的呼叫CGI ::应用程序应用程序,就像我从网上运行它一样?

在进一步挖掘了CGI::AppCGI文档后,它似乎比我想象的更直接。最简单的情况下(没有真正的参数处理或处理从web应用程序运行调用的输出)为:

#!/usr/bin/perl 

use strict; 
use warnings; 

use CGI; 
use WebApp; 

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

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

它采取了一系列空间分隔的名称值对创建CGI。您需要传递运行模式和所有参数。

正是如此:

$ perl yourscript.pl field1=value1 field2=value2 

Perl的CGI库负责的魔力为你,并且看起来CGI ::应用程序依赖CGI(从他们的示例代码判断)。

+0

您还需要设置各种环境变量,模拟的东西Web服务器会成立。 CGI.pm寻找那些知道该怎么做的人。 – 2009-07-16 23:46:16

+0

@brian d foy:除非你的代码由于某些原因取决于那些;没有它们,CGI.pm没有问题。 – ysth 2009-07-17 02:37:12

+0

@ysth:如果这个运行模式有副作用,它应该使用POST,因为它不是一个幂等的请求。在这种情况下,你必须添加-debug到CGI.pm的导入来让这些东西起作用。这是对代码的改变,也有副作用。正如George所说的那样做起来要容易得多。 – 2009-07-17 04:53:47

每次你想完成某些事情时,不需要通过CGI :: Application,而是可以使用MVC设置来强制执行正确的separation of concerns。所有的功能都应该存在于CGI :: Application之外,因为它只能用作控制器。一旦分离出这些位,就可以轻松地为其他输入方法编写其他控制器。

不要写Web应用程序;编写一个恰好具有Web界面的应用程序。当你有这些时,你可以很容易地给你的应用程序提供其他类型的接口。

+0

我完全同意,有一个库可以完成产生结果的实际工作,并且我试图限制CGI :: A的'Controller'部分中的代码量,直到它刚才的格式化为止。它只是我认为可以使用CGI :: App发送电子邮件而不是编写另一个脚本来调用库的“懒惰”部分。 – 2009-07-17 00:47:36

+0

那么,懒惰与大写L可以让你轻松地做其他任务,而无需以后的工作:懒惰不是避免工作,而是为了节省时间以后的前期工作。 – 2009-07-17 04:54:27

原始CGI specification可以轻松地从命令行运行,并且完全不是作为特定的纯HTTP接口,而是可以处理FTP和gopher以及新的顶级URL方案的东西。当我帮忙指定时,我知道我想要什么。

我引用的规范应该给你所有你需要的规范,但大多数情况下它只是一个环境变量的集合。如果你看到一个请求:

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

环境变量出来找这样的:

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

要扭转的是,在Perl的极性会去是这样的:

$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"); 

事情在处理POST查询时会稍微复杂一点,并且可能需要更多可能的环境变量。最糟糕的情况下,你可以列举他们都具有快速CGI脚本是这样的:

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

现在把Web服务器上,以替代CGI脚本,你会看到,在得到通过的所有环境(和原始的环境,所以你需要做几个判断呼叫)。

您可以通过使用curl,wget或具有适当参数的LWP GET脚本调用Web应用程序来实现自动化。我用Catalyst应用程序为cron驱动的任务使用了类似的系统。

这一切对你的环境变量涉及..

我CGI的维护者::应用程序,我做这一切的时间 - 我有CGI内置cron脚本的十几::应用程序,因为它与应用程序共享基础架构很方便。

最简单的办法是这样的:

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

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

在该示例中,你绕过正常的流动和直接调用的方法。在这种情况下,确保你不需要任何“设置”或“拆卸”动作。

如果你只有一个你正在调用的运行模式,你也可以直接设置“start_mode”,然后调用run(),这样就默认调用了默认运行模式。

另一个想法:你可以使用像Getopt :: Long这样的模块,并通过PARAM哈希值传递给new(),或者完全替换运行模式选择过程。在此处,命令行标志来确定运行模式的例子:

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(); 
    }); 
}