为什么我的系统调用另一个CGI脚本在命令行上运行,但在作为CGI程序运行时却不行?

时间:2010-01-04 22:14:33

标签: perl cgi

我有一个调用scriptB.cgi的scriptA.cgi。

scriptB.cgi需要一个参数。

我试过了两个 在scriptA.cgi里面我试过了:

`perl -l scriptB.cgi foo="toast is good" `;

以及

@args = ("perl", "-l", "scriptB.cgi", "foo=\"toast is good\"");
system(@args);

当我从命令行调用scriptA.cgi时,它按预期工作。 但是,当我通过浏览器调用scriptA.cgi时,脚本执行了。执行但是它无法读取传入的参数并将foo打印为空。

是否有一种不那么丑陋的方式从另一个调用一个cgi并传入params?

scriptB不一定是cgi,如果用直接的.pl和args更容易做到这一点,我也很乐意这样做......但arg必须是带空格的带引号的字符串。 / p>

欢迎所有的想法。

6 个答案:

答案 0 :(得分:5)

如果许多脚本之间共享共同功能,请将其放在模块中

模块可能看起来很吓人,但它们非常简单。

档案SMSTools.pm

package SMSTools;
use strict;
use warnings;
use Exporter qw(import);

# Name subs (and variables, but don't do that) to export to calling code:
our @EXPORT_OK = qw( send_sms_message );

our @EXPORT = @EXPORT_OK;  
# Generally you should export nothing by default.
# However, for simple cases where there is only one key function
# provided by a module, I believe it is reasonable to export it by default.


sub send_sms_message {
    my $phone_number = shift;
    my $message      = shift;

    # Do stuff.

    return; # Return true on successful send.
}

# Various supporting subroutines as needed.

1;  # Any true value.

现在,在foo.cgi中使用您的模块:

use strict;
use warnings;
use CGI;

use SMSTools;

my $q = CGI->new;

my $number = $q->param_fetch( 'number');
my $message = $q->param_fetch( 'msg');

print 
    $q->header,
    $q->start_html,
    (    send_sms_message($number, $message) 
         ? $q->h1("Sent SMS Message") 
         : $q->h1("Message Failed")
    ),
    q->end_html; 

有关详细信息,请参阅perlmodthe docs for Exporter

答案 1 :(得分:2)

我怀疑CGI环境正在阻碍你。你在使用CGI.pm吗?

从命令行运行CGI脚本时,可能没有设置任何CGI环境变量,例如QUERY_STRING。 CGI脚本启动,注意到它缺少那些环境变量,并认为它必须是从命令行运行的。如果它认为它已从命令行运行,则它会在其他位置(例如@ARGV)查找数据。那是我的第一次猜测。

CGI计划案例中可能会发生各种各样的事情。很可能,scriptB.cgi对scriptA.cgi使用相同的环境设置,并且它没有预期的参数或数据。由于CGI环境已设置且存在QUERY_STRING变量,因此它永远不会考虑查看@ARGV

但是,你有很多选择,具体取决于你想做什么(这有点超出你的情况):

  • 如果您只需要scriptB.cgi来支持其他脚本(即浏览器不应该直接调用它),请将其设为库或模块。你应该总是尝试这样做。让每个脚本至少成为modulino。

  • 如果scriptB.cgi是一个独立的CGI脚本并且应该保持这种状态,请在scriptA.cgi中创建一个子请求,以便通过服务器设置所有正常的CGI内容。

  • 如果您不想进行子请求,请本地化%ENV,子进程将共享,并自行伪造CGI环境。这有点工作,但不是太难。

答案 2 :(得分:1)

请参阅“解码表单输出”:

http://www.cgi101.com/class/ch4/text.html

(她的post.cgi脚本在诊断此问题时对我来说非常宝贵。)

对于那些使用CGI.pm的人来说还有另一件需要注意的事情 - 它使用multipart/form-data作为其默认编码类型,“它适用于......用于传输二进制数据的表单。 “有趣的是,将编码类型更改为另一个选项使一切都按预期工作:

enctype=>"application/x-www-form-urlencoded"

(使用Windows XP,Perl 5.10,CGI.pm 3.43和Apache 2测试)

答案 3 :(得分:1)

一个选项也是使用hidden field在CGI脚本之间传递参数。顾名思义,这些字段对用户不可见,但可以像其他任何字段一样用于传递参数。

答案 4 :(得分:0)

以下是我编写的一些代码片段,其中包含一个调用Perl脚本的 *。cgi 脚本:

$note = "toast is good";
$cmd = "addAccTrans.pl $priAcc $date $priGrp \"$note\" $amt";<br />
open($f, "perl $cmd|");<br />
while(<$f>) { print "$_\n" };<br />
close($f);<br />

CGI脚本捕获Perl脚本的输出并再次打印出来。

答案 5 :(得分:-1)

A:

#!/usr/bin/perl
print "Content-type: text/html\n\n";
{
    local $foo = "toas is bad";
    do 'b.cgi';
}

B:

#!/usr/bin/perl
print "$foo";