从CGI迁移到mod_perl。了解我的,我们的,本地的

时间:2012-10-23 05:48:36

标签: perl scope mod-perl mod-perl2

几年来我一直在使用apache mod_cgi。现在我转向mod_perl,我发现了一些问题,特别是子程序。到现在为止,我从未使用myourlocal;并且CGI脚本没有问题。在阅读了文档甚至是此处发布的一些先前问题后,我或多或少了解myourlocal的工作原理。我担心的是下一个请求之间将共享哪些信息(如果我理解正确的话,这是我在运行mod_perl而不是mod_cgi时必须具备的主要问题)。

  • 在标量中使用our还是仅使用标量而不声明my等特殊内容之间是否有任何区别?不是全球性的吗?
  • 如果我没有声明标量为私有,将在下一个请求中共享?即使在同一服务器中另一个perl脚本的另一个请求中呢?
  • 如何将子程序中的标量值共享到该子程序之外,但不能在同一文件之外或同一请求之外?
  • 如果我在文件的同一级别或同一子例程中的my内的标量中使用if,之后我创建另一个if我使用的if相同的标量;是if或每个while之间共享的标量意味着不同的块?那么formy呢,它们是先前声明为{{1}}标量的不同块,还是仅适用于子程序和文件?

2 个答案:

答案 0 :(得分:17)

mod_perl 的工作方式是将每个Perl脚本包装在一个名为handler的子例程中,该子例程基于脚本的名称和路径。而不是启动一个新进程来运行每个脚本,这个handler子例程由许多持久的Perl theads中的一个调用。

通常这些知识可以帮助理解来自 mod_cgi 的环境变化,但是因为你从未在程序中添加use strict并熟悉声明变量的工作原理有很多事情要做!

mod_perl 环境有可能导致非明显的安全漏洞,您现在应该开始{em>每个脚本上的use strict并声明每个变量。 use Carp还可以帮助您了解错误日志。

使用our声明的变量名是具有相同名称的包变量的词法范围同义词,可以在不通过包含包名完全限定名称的情况下使用该变量。例如,通常使用our $var声明的变量将提供对$main::var标量的访问(如果没有前面的package声明),而不指定main::。但是,在 mod_cgi 中以undef值开始生效的变量现在将保留其先前执行任何给定 mod_perl 线程的值,并保持一致性在声明时总是初始化它们是最安全的。另请注意,由于 mod_perl 的包装,默认包名称不再是main,因此您无法再使用main::前缀访问包变量,它是不明智地找到包的实际名称并明确使用它,因为它将是非常长名称,并且如果您移动或重命名脚本将会更改。

my变量是独立于包符号表存在的变量,通常其生命周期是封闭文件(对于在文件范围内声明的变量)或子例程的运行时间。如果在脚本的文件范围内声明和使用它们,或者完全在一个子例程中,它们在 mod_perl 中都是安全的,但是如果混合范围并在文件范围内声明my $global,则可能会受到攻击。然后尝试在子程序中使用它。这样做的原因并不简单,但它是由 mod_perl 将脚本包装在handler子例程中引起的,因此您有嵌套的子例程声明。内部子例程将倾向于仅采用$global的第一个实例化,并忽略稍后调用handler创建的任何其他实例。如果您需要一个全局变量,您应该使用our声明它并在该声明中初始化它,如上所述。

local变量非常类似于our变量,因为它形成了包变量的同义词。但是,它会暂时保存该变量的当前值,并提供一个新副本以供使用,直到文件或块作用域结束。由于它在其范围内自动创建和删除,因此它可以替代 mod_perl 脚本中的my变量,特别是在使用指向数据结构的指针时,例如,实例CGI类的。{声明our $cgi = CGI->new会正确创建对象,但由于 mod_perl 持久性,会将其留在内存中,直到线程的下一次执行删除它为另一个执行腾出空间。

关于你的问题:

  • 如果use strict到位,则使用变量而不声明它会导致编译时错误。否则,它是当前包命名空间中该变量的同义词。

  • 变量是包变量或词法变量;没有办法将变量声明为 private 。除非您通过编写使用在更广泛的范围,当变量将持久但不会做你想要的。使用my声明的变量将在脚本调用之间保留其值,而使用our声明的变量将在脚本终止时被销毁。 localour变量都是包变量,对同一变量名的所有引用都引用相同的变量。

  • 要声明在脚本的任何一次调用中始终可访问的变量,您可以使用local变量或初始化的local变量。文件范围our在很大程度上等同于 mod_perl 脚本的local $global。如果您使用our $global = undef变量指向数据结构,请记得使用our在脚本末尾销毁它。

  • undef $global变量对于声明它们的块是唯一的,并且在其中可见,无论是myif还是{{1或者甚至只是一个裸while块范围。始终将for变量用于临时工作变量,这些变量仅在块中使用,并且可以从其他任何地方访问。

我希望这会有所帮助

答案 1 :(得分:8)

编辑:这是关于Perl变量范围的一般信息。有关具体的mod_perl问题,请参阅Borodin的帖子。

my声明的变量是词法。换句话说,它们仅存在于当前范围内。您应该默认使用my声明所有变量;当你特别想要不同的功能时,只做别的事。

使用词法范围的变量是(几乎)任何语言的良好代码设计的基本部分。将use strict;use warnings;放入所有脚本中将需要您遵循此良好做法。

our是一种声明全局变量的方法;底层结果与使用未声明的全局变量非常相似。但是,它有两点不同:

  1. 您明确声明您希望变量是全局变量。这是一个很好的做法,因为使用全局变量应该是一个例外情况。因此,即使您use strict;,也可以通过这种方式创建全局。
  2. 使用our声明的变量可以通过您在当前范围内的所有包中声明的名称访问。相反,未声明的变量只能通过当前包中的简单名称访问。除此之外,您只能将其称为$package::variable
  3. 有关详细信息,请参阅the documentation for our

    local不会创建词法变量;相反,它是一种在当前范围内为全局变量赋予临时值的方法。它主要与Perl的特殊内置(标点符号)变量一起使用:

    {
       local $/; #make the record separator undefined in this scope only.
       my $file = <FILE>; #read in an entire file at once.
    }
    

    您可以随时使用my始终使用local进行变量,并仅将{{1}}用于上述特殊情况。