最近关于SO的一个问题让我思考.
在我尝试的大多数Linux发行版中,一些Perl模块可以通过包管理器获得.其他人当然不是.很长一段时间,每当我需要安装一些CPAN模块以确定软件包是否可用时,我会使用我的软件包管理器,并在需要时安装它.
显而易见的优点是,只要有新版本的软件包,就可以更新模块.
但是,如果模块没有预先打包的形式,并且该模块存在依赖关系,则会遇到麻烦.每次cpan shell询问是否应该遵循依赖关系时,启动你的包管理器都会非常累人.
通常,另一个缺点是预封装模块的版本.如果您正在运行Debian或Ubuntu,您很快就会发现,您将无法像最近的CPAN模块作者那样生活在最前沿.
Linux上的其他Perl人如何处理这个问题?你只是忽略你的包经理提供的东西吗?是否有任何工具可以使apt(例如)和cpan更好的队友?或者你只是不通过cpan shell安装任何东西?
为了开发,我安装了自己的Perl并将系统保留在Perl中.如果我想升级系统Perl,我使用系统包管理器.对于我的开发Perl,我使用cpan工具.
由于我将这些分开,我不应该把系统所需的Perl搞砸到维护任务等等,但我不必依赖系统的开发决策.
安装单独的Perls非常容易.从源代码分发中运行Configure时,它会询问您要在哪里安装所有内容.给它任何你喜欢的路径.例如,我在/ usr/local/perls中安装了许多Perls ,并且每个安装的所有内容都是分开的.然后我在/ usr/local/bin中为它们创建符号链接(例如perl5.8.9,perl.5.10.0,perl5.10.0-threaded).当我需要特定版本时,我只使用我想要的版本:
$ perl5.10.0 program.pl
特定的二进制文件确保程序选择正确的模块搜索路径等等(这与该二进制文件的Config.pm模块中的内容相同).
这是我用来创建符号链接的脚本.它查看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博客中写了更多关于此类事情的文章:
建立每个版本工具的链接.
使用Git管理您的Perl模块.
我们通过CPAN shell安装所有内容.这确实忽略了包管理器必须提供的功能,但它避免了您在尝试使用它们时提到的麻烦(使用正确的版本触发依赖项).
此外,这意味着我们的包可以在CPAN运行的任何平台上以编程方式(或通过shell手动)构建.依赖于包管理器会影响您将软件分发到不使用/支持该包管理器的平台的能力.
由于这个问题最初被问到,perlbrew已经发布.它使安装自定义,自包含的perl安装变得微不足道.在这些版本之间切换也很简单:
perlbrew switch $version
我在所有盒子上做了以下事情:
我编译自己的perl:我仍然使用5.8.[89] 大多数情况下,股票5.10.0有一个性能回归,给我很多,等待5.10.1重新尝试;
我使用(强烈推荐)local :: lib模块来保存每个项目的模块目录.现在,该目录与所有安装项目的服务器进行了rsync,但我正在使用git进行测试;
我为每个项目创建一个Task ::模块,这样我就可以用一个命令安装所有依赖项.
我正在使用Debian进行开发和生产,并依赖于随发行版提供的debian Perl软件包.
对于我需要一个debian中没有的Perl模块的情况,我通常会创建自己的debian软件包并安装它.
当然,这种方法并非没有缺点,因为很多debian perl模块已经过时(至少在目前的debian稳定版本中是蚀刻版本),并且向后移植具有大量依赖性的类似Catalyst的东西是不切实际的.
但是,通过依赖操作系统软件包管理器,我保留了它的所有强大功能,这使得易于维护,特别是对于已部署的服务器,因为您确切知道安装了哪些软件包,以及简单apt-get update;apt-get upgrade
(来自debian或来自本地存储库) )将所有服务器升级到相同的状态,包括Perl模块.