我有一个面向对象的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";
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
FindBin :: libs非常适合.我已经在大型系统中使用了一段时间而没有任何问题.
默认调用看起来对你有用,只需:
use FindBin::libs;
Run Code Online (Sandbox Code Playgroud)
这将搜索./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!)
Run Code Online (Sandbox Code Playgroud)
任何它被添加到您认为@INC有use lib.
但是,如果这不是您所需要的,那么它就是一个非常灵活的模块.如果你找不到办法让它做你想做的事,我会感到惊讶.
如果您从命令行运行程序,请不要以编程方式设置lib:只需将其作为参数传递,例如:perl -I/location/of/my/lib myprog.pl.
对于您的Web应用程序,为什么不使您的库相对于脚本本身的位置?然后只需将它安装在库所在的每台机器上.
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;
}
Run Code Online (Sandbox Code Playgroud)
当然,最简单的选择是不使用不同的lib目录.为什么不能在所有环境中保持一致?
编辑.重新评论"我必须使用不同的lib目录的原因是因为在实际站点中运行的代码与在beta站点上运行的代码不同......这就是拥有测试版网站的重点." - 为什么不在安装程序级别处理此问题,而不是让代码本身必须知道它是实时还是测试版?例如,像现在一样将代码存储在源代码树的不同目录中,但只将相关代码安装到每个框中.毕竟,这正是一个好的修订控制系统会为你做的 - 你一次只能检查一个分支,你应该一次只安装一个版本的代码(正如brian d foy所提到的).