我有一个面向对象的Web应用程序,它安装在我服务器上的多个位置。一次用于“live”,一次用于“beta”等。面向对象,它由许多perl模块组成。在主模块中,我必须“使用lib”适用于该应用程序实例的所有自定义 perl模块的相应目录。
这没什么大不了的,我有一个BEGIN块来检查主程序的位置并适当地设置库目录。但是我也有很多实用程序,命令行程序需要做同样的事情。我不想在任何地方剪切和粘贴此代码。
在需要它的各种程序中共享此代码段的最佳方法是什么?
我无法“使用”它,因为尚未设置libary路径。也许“做”或“要求”将是正确的答案,但这两者都会搜索@INC,这是不合适的。
也许像eval `cat GetLib.pl`;
这样的东西是合适的,但它似乎有点笨拙和脆弱。
这是我目前使用的BEGIN块:
BEGIN {
use FindBin qw ($Bin);
require lib;
if ($Bin =~ /^\/home\/w\/myapp_live/) {
lib->import('/home/w/myapp_live/lib');
print STDERR "live site\n";
}
if ($Bin =~ /^\/home\/w\/myapp_beta/) {
lib->import('/home/w/myapp_beta/lib');
print STDERR "beta site\n";
}
if ($Bin =~ /^\/home\/w\/myapp_test/) {
lib->import('/home/w/myapp_test/lib');
print STDERR "testing site\n";
}
}
谢谢!
答案 0 :(得分:7)
FindBin::libs非常出色。我已经在大型系统中使用了一段时间而没有任何问题。
默认调用看起来对你有用,只需:
use FindBin::libs;
这将在当前文件的目录的所有父目录中搜索所有./lib
目录,并use lib
它们。因此,例如,如果您的脚本位于/home/w/myapp_live/scripts/defurblise_widgets.pl
(和use()
es FindBin :: libs)中,它将查找:
/home/w/myapp_live/scripts/lib
/home/w/myapp_live/lib
/home/w/lib
/home/lib
/lib # (presumably!)
它找到的任何内容都会@INC
与use lib
一起添加到您。
但是,如果这不是您所需要的,那么这是一个非常灵活的模块。如果你找不到办法让它做你想做的事,我会感到惊讶。
答案 1 :(得分:5)
如果从命令行运行程序,请不要以编程方式设置lib:只需将其作为参数传递,例如:perl -I/location/of/my/lib myprog.pl
。
对于您的网络应用,为什么不使您的图书馆相对于脚本本身的位置?然后将它安装在库所在的每台机器上。
use FindBin;
use File::Spec::Functions;
use Cwd qw(abs_path getcwd);
BEGIN {
my $curdir = getcwd;
my $selfdir = $FindBin::Bin;
my $libdir = abs_path(catdir($selfdir, 'lib'));
chdir $libdir or die "can't chdir to $libdir: $@";
use lib $libdir;
}
当然,最简单的选择是不使用不同的lib目录。为什么不能在所有环境中保持一致?
编辑。重新评论“我必须使用不同的lib目录的原因是因为在实际站点中运行的代码与在beta站点上运行的代码不同......这就是拥有测试版网站的重点。” - 为什么不在安装程序级别处理此问题,而不是让代码本身必须知道它是实时还是测试版?例如将代码存储在源树中的不同目录中,就像现在一样,但只将相关代码安装到每个框中。毕竟,这正是一个好的修订控制系统会为你做的 - 你一次只能检查一个分支,你应该一次只安装一个版本的代码(正如brian d foy所暗示的那样)。 / p>
答案 2 :(得分:3)
我在许多脚本中使用以下内容:
use strict;
use warnings;
use 5.008;
use FindBin;
use lib $FindBin::Bin;
最后一行可以这样修改:
use FindBin;
use lib "$FindBin::Bin/lib";
答案 3 :(得分:2)
不同的环境可能对环境变量$PERL5LIB
有不同的设置。
答案 4 :(得分:1)
您展示的代码看起来很合理。您可以将该代码的一个副本安装到系统范围的位置,然后调用它的代码将归结为
require '/path/to/findlib.pl';
findlib->import;
采用文件名的require
形式搜索@INC
。
作为替代方案,如果您想要改变很多东西,可以考虑以对local::lib用法更友好的方式部署应用程序。