如何根据安装位置“使用lib”相应的目录?

时间:2009-11-11 00:53:06

标签: perl

我有一个面向对象的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";
  }

}

谢谢!

5 个答案:

答案 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!)

它找到的任何内容都会@INCuse 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用法更友好的方式部署应用程序。

相关问题