某些perl文件中的行为不一致且莫名其妙

时间:2012-01-02 06:54:32

标签: perl

主机是Linux。我在同一目录中有多个文件。所有*.pl文件在开头都包含以下内容,仅在注释中有所不同:

#!/usr/bin/perl -w

BEGIN { chdir('/home/httpd/vhosts/mysite.com/httpdocs/newsbot'); unshift(@INC, "/home/httpd/vhosts/mysite.com/httpdocs/newsbot"); }

use Form;
use File;
use Mysite;

#Read in All Form Variables
&ReadInForm;

文件Form.pm包含ReadInForm子例程,没有别的。

sub ReadInForm { 
}    
1;

奇怪的是,上面的输出是完全不一致的。有时它执行正常,但在脚本末尾显示“内部服务器错误”消息,并将以下内容放在error_log文件中:

  

参数“”在/usr/lib64/perl5/vendor_perl/5.8.8/x86_64-linux-thread-multi/ModPerl/RegistryCooker.pm第171行的子例程条目中不是数字。\ n,referer:{{ 3}}

其他时候,它不会执行,并将以下内容输出到浏览器:

  

Undefined subroutine& ModPerl :: ROOT :: ModPerl :: Registry :: home_httpd_vhosts_mysite_2ecom_httpdocs_newsbot_groupkeywords_2epl :: ReadInForm,在/home/httpd/vhosts/mysite.com/httpdocs/newsbot/groupkeywords.pl第11行调用。

其他时候它正常工作,没有错误。

奇怪的是它不一致。我可以从文件中获取一个输出,几分钟后刷新,然后获取另一个。我甚至有一些“内部服务器错误”消息和一个500响应标题,没有实际内容。评论&ReadInForm;行每次都会解决问题,因此我将其缩小到了这一点,但是我在Form.pm中放入的内容并不重要。我甚至可以设置一个空的子程序(如上所述)但它仍然无法解决问题。

我甚至不确定如何调试它。它怎么可能不一致呢? perl编译器是否在幕后缓存?

2 个答案:

答案 0 :(得分:5)

显然你的主机正在使用Apache mod_perl。您必须为mod_perl显式编码。顺便说一句,你的代码闻起来有perl 4和cgi-lib.pl,1996年份。简单地说,在mod_perl下你的脚本无法工作,因为无论如何global variables are completely forbiddenyou can't modify @INC under mod_perl。 你最好在脚本中加上“use strict; use warnings;”,并使用适当的CGI或mod_perl形式解析模块和函数。

但是,这种代码风格应该有效:

#!/usr/bin/perl

# I don't know what this BEGIN block is for, but I suspect it may not work or causes subtle bugs...
BEGIN { chdir('/home/httpd/vhosts/mysite.com/httpdocs/newsbot'); }


use strict;
use warnings;
use Form;
use File;
use Mysite;

#Read in All Form Variables
Form::ReadInForm();

使用Form.pm:

use strict;
use warnings;

package Form;

sub ReadInForm { 
}    
1;

编辑:如果你的代码是旧的并且想要为你进行大修,你可以创建一个包含所有脚本代码和变量声明的“main”子,并简单地调用它这样:

旧脚本:

#!/usr/bin/perl

# the following line will fail with "undeclared variable" under "use strict"
$a="test";
print "$a\n";

新脚本:

#!/usr/bin/perl

use strict; 
use warnings;

# call the main loop enclosing everything else    
main();

sub main {
    # first declare all variables
    my $a;

    # then add there all the code:
    $a="test";
    print "$a\n";
}

通过这种方式,脚本可以廉价而快速地“现代化”。

答案 1 :(得分:0)

在2017年的这个晚些时候,根据我最近的类似经历,我有一件事要添加到这个帖子中。对我来说很明显,旧的1990年的遗留perl代码在mod_perl下运行时会遇到奇怪的错误,正如(http://www.fifi.org/cgi-bin/man2html/usr/share/man/man3/mod_perl_traps.3pm.gz)中清楚简洁地解释的那样。从其他文档中可以明显看出,由于线程重用,创建mod_perl是为了将perl服务器代码加速35倍,但必须避免使用某些旧的perl CGI实践来使这项工作干净利落。

理论上这是伟大的!但并不总是......

我的一个警告建议是这里的perl_mod guru社区的爱好者。在决定如何运行遗留的perl时,不要自动建议使用mod_perl,从而迫使随后的一些意外的代码更改在毫无疑问的传统perl代码移植人身上。

首先确定遗留代码是否需要以最高效率运行(在大量使用的可重用线程环境下),或者老式单线程CGI是否正常。

就像我的情况一样。我在1998年写了一个很棒的CGI perl在线订购系统。这是同类产品中的第一个。现在(2017年)我想部署它只是为了演示我编写的一些旧代码(如简历项目)。除了作为演示之外,它永远不会被运行。

所以,mod_perl是OVERKILL,但我的新托管网站上的SysAdmins坚持我安装了mod_perl,我收集的是他们建议的共同习惯,但后来我很清楚他们对mod_perl做什么一无所知。旧的CGI perl系统。但当时我也没有。所以,我按照他们的要求做了,然后才知道mod_perl陷阱,因为我一个接一个地陷入了它们。

如果我没有加载mod_perl,那么这些错误都不会发生,因为服务器的默认配置是旧式的CGI。

警告Emptor。