如何在使用包pipe理器时pipe理Perl模块?

这个最近的问题让我思考。

在我尝试的大多数Linux发行版中,通过包pipe理器可以使用一些Perl模块。 其他人当然不是。 有一段时间我会用我的包pipe理器,每当我需要安装一些CPAN模块,以确定包是否可用,并安装它时。

显而易见的好处是,只要新版本的软件包可用,就可以更新模块。

但是,如果模块不能以预封装的forms提供,并且该模块存在依赖关系,则会遇到麻烦。 每当cpan shell询问是否应该依赖依赖时,打包你的包pipe理器可能会相当累人。

另一个缺点是预封装模块的版本。 如果您正在运行Debian或Ubuntu,您很快就会发现,您将无法生活在stream血的边缘,就像许多CPAN模块作者似乎所做的那样。

Linux上的其他Perl人员如何处理这个问题? 你只是忽略你的软件包pipe理者所提供的? 是否有任何工具可以使(例如)更好的队友? 或者你只是不通过cpanshell安装任何东西?

由于这个问题最初被问到, perlbrew已经被释放。 它使得安装自定义,独立的perl安装变得微不足道。 而在这些版本之间切换也很简单:

perlbrew switch $version 

为了开发,我安装了我自己的Perl,并让系统Perl独自一人。 如果我想升级系统Perl,我使用系统包pipe理器。 对于我的Perl开发,我使用cpan工具。

既然我把它们分开了,我不应该把系统维护任务所需要的Perl搞糊涂了,但是我不必依靠系统的开发决策。

安装单独的Perls很容易。 从源代码发行版运行configuration时,它会询问您要在何处安装所有内容。 给它任何你喜欢的path。 例如,我在/ usr / local / perls中安装了许多Perls,并且每个安装的所有内容都单独存在。 然后,我在/ usr / local / bin中为它们创build符号链接(例如,perl5.8.9,perl.5.10.0,perl5.10.0-threaded)。 当我想要一个特定的版本,我只是使用我想要的一个:

 $ perl5.10.0 program.pl 

特定的二进制文件确保程序select正确的模块searchpath等等(这与Config.pm模块中的二进制文件是一样的)。

这是我用来创build符号链接的脚本。 它看起来在bin目录中,找出Perl的版本,并使链接如cpan5.10.1等。 每个程序已经知道正确的Perl调用:

 #!perl use 5.010; use strict; use warnings; use File::Basename; use File::Spec::Functions; my $perls_directory = catfile( $ARGV[0] // '/usr/local/perls', 'perl*' ); die "$perls_directory does not exist!\n" unless -d dirname $perls_directory; my $links_directory = $ARGV[1] // catfile( $ENV{HOME}, 'bin' ); #/ die "$links_directory does not exist!\n" unless -d $links_directory; foreach my $directory ( glob( $perls_directory ) ) { say "Processing $directory..."; unless( -e catfile( $directory, 'bin' ) ) { say "\tNo bin/ directory. Skipping!"; next; } my @perls = glob( catfile( $directory, qw( bin perl5* ) ) ); my( $perl_version ) = $perls[0] =~ m/(5\.\d+\.\d+)\z/; say "\tperl version is $perl_version"; foreach my $bin ( glob( catfile( $directory, 'bin', '*' ) ) ) { say "\tFound $bin"; my $basename = basename( $bin ); my $link_basename = do { if( $basename =~ m/5\.\d+\.\d+\z/) { $basename } else { "$basename$perl_version" } }; my $link = catfile( $links_directory, $link_basename ); next if -e $link; say "\t\tlinking $bin => $link"; symlink $bin => $link or warn "\t\tCould not create symlink [$!]: $bin => $link!"; } } 

一切都得到安装在适当的地方为特定的Perl。

我也一直在想,我应该把这些Perl目录放在某种源代码控制之下。 如果我添加一个模块,我不喜欢,我只是退出到一个较早的版本。 我只是开始这样做,并没有玩得太多。

我在Effective Perler博客上写了更多关于这种事情的文章:

  • build立链接到每个版本的工具。
  • 用Gitpipe理你的Perl模块。

我们通过CPAN shell安装所有的东西。 这确实忽略了软件包pipe理者必须提供的function,但是它避免了在尝试使用它们(使用正确版本进行依赖关系)时所提到的令人头疼的问题。

另外,这意味着我们的软件包可以在CPAN运行的任何平台上以编程方式构build(或通过shell手动构build)。 依赖于软件包pipe理器会影响您将软件分发到不使用/支持软件包pipe理器的平台的能力。

我正在使用Debian进行开发和生产,并依赖于随发行版提供的debian Perl包。

对于需要debian中没有的Perl模块的情况,我通常会创build自己的debian软件包并安装它。

当然,这个方法并不是没有问题,因为许多debian perl模块已经过时了(至less在目前的debian稳定版本中是 – etch),而像Catalyst这样有很多依赖的东西是不现实的。

但是,依靠OS软件包pipe理器,我保留了它的所有优点,这使得易于维护,尤其是对于部署的服务器,因为您确切知道安装了哪些软件包,以及简单的apt-get update;apt-get upgrade (从debian或从本地存储库)将所有服务器升级到相同的状态,包括Perl模块。

我在我的箱子上做了以下几件事:

  • 我编译我自己的Perl:我仍然使用5.8。[89] 多数情况下,股票5.10.0有一个performance回落,打了很多,等待5.10.1再试一次;
  • 我使用(并强烈推荐)local :: lib模块来保持每个项目的模块目录。 现在,该目录已rsync'ed所有的服务器安装项目,但我使用gittesting,而不是;
  • 我为每个项目创build一个Task ::模块,这样我就可以用一个命令安装所有的依赖关系。

我也使用cpan shell和local :: lib。

你不应该为每个项目需要一个Task ::。 只需使用Module :: Install(我喜欢像这样使用Module :: Starter:

 $ module-starter --mi --module=Module::Name --author="Me" --email=me@cpan.org 

然后在需要'module :: dependency'的地方popup你的依赖关系。 在Makefile.PL中。 最后在安装的时候,你只需要perl Makefile.PL (回答是)然后make installdeps

从我最初给出这个答案的5年后,

这些天perlbrew和cpanm是使用的东西。 local :: lib仍然有一个用例,但是perlbrew和cpanm的组合解决了这些情况的一个超集。 当你不准备编译自己的perl的时候使用local :: lib。

我build议只使用cpan。 在Linux发行版中包含的模块只是为了涵盖软件包依赖性。 当你安装没有上网function的linux只有CD的时候,它不能使用cpan,所以一些模块被包含在软件包中,但是对于Perl开发者来说这是不好的。

此外,我曾经有一个cpanconfiguration为在我的家庭(.perl)没有根login需要安装模块。

为了生产:

在开发过程中,select一个适合需求的perl模块版本; 如果可能的话select目标操作系统的发行版本(这使得以下大部分是多余的),否则,select另一个。 为它创build一个RPM spec文件。 使用clean build VM以可重现的方式(从相应分支上签入的specfile / source)构buildRPM。

当最终的构build(合并之后)可以被构build时,从发行版分支执行相同的构build,将生成的RPM提交到部署库中。 这将在最终validation中使用,然后通过复制到生产库进行生产。

生产中的所有服务器都使用完全相同的二进制文件, 他们使用相同的规格文件和来源作为开发者的意图。

Perl模块不会被任何不遵循这个模型的进程所升级。 也没有任何其他生产软件。

我使用FreeBSD的端口,并把所有的CPAN依赖关系作为一种本地端口包装在“元端口”中。 FreeBSD拥有相当多的CPAN模块,它们的构build系统是平易近人的 ,如果它不存在,你可以很容易地编写你自己的端口 – 只是不要忘了提交这个端口,所以它被包含在ports树中。 如果该端口没有当前版本的库存,则可以随时编辑该端口的Makefile,以便使用新版本,同样不要忘记提交更改 :-)。

最后,我使用Tinderbox作为二进制包来构build整个混乱,然后安装在所有的生产和开发机器上。

底线 – 一旦你克服了编辑Makefiles的恐惧症,FreeBSD的端口是维护你的perl应用程序及其依赖的一个好方法。

我最近开始使用Gentoo,Gentoo在这方面有几个非常重要的优势。 首先, g-cpan通常可以安装CPAN中的许多(尽pipe不是全部)模块,因为Gentoo软件包本身就是这样,尽pipe更新成为了一个问题。

通常在Gentoo上,我的方法是使用g-cpan创build一个ebuild文件,然后根据需要进行安装。 优点是升级变得非常简单。 然后我把文件从g-cpan / perl移到dev-perl,并放在一个覆盖层上供其他人使用。 这使我能够快速处理案件g-cpan不和gentoo包装是一件轻而易举的事情/