升级local :: lib安装的所有模块

时间:2014-09-02 10:06:00

标签: perl locallib

我一直在使用local :: lib来处理服务器上Perl模块的安装,这样我就可以为一些开发工作获得正确的版本而不会污染系统安装。

但是,系统管理员最近将Perl从5.16升级到5.18,我现在收到与二进制模块有关的错误,例如

perl -e 'use Scalar::Util'
Perl API version v5.16.0 of List::Util does not match v5.18.0 at /usr/lib64/perl5/5.18.2/XSLoader.pm line 92.
Compilation failed in require at /home/paul/perl5/lib/perl5/x86_64-linux/Scalar/Util.pm line 11.
Compilation failed in require at -e line 1.
BEGIN failed--compilation aborted at -e line 1.

我的理解是我可以通过强制local :: lib重建其所有模块来解决问题,但是我无法在文档中找到任何告诉我如何执行此操作的内容,甚至是如何获取使用local :: lib安装的所有模块的列表(如果我在每行一个模块中有这个模块,我可以轻松编写一个Bash脚本来处理它)。

这是可能的,还是我必须删除〜/ perl5目录并从头开始重新安装所有模块(可能会遗漏一些,因为我无法记住它们)?

2 个答案:

答案 0 :(得分:5)

更新 :一段时间以来,INSTALL_BASE一直在制作更好的目录结构,以避免新安装出现此问题。

这就是为什么install :: lib使用的perl Makefile.PL INSTALL_BASE=...约定(以及Build.PL的相应约定)糟透了。

删除(或重命名目录以便备份)是最简单的解决方案。您可以通过查找.pm个文件找到已安装的内容。

cd ~
mv perl5{,16}
cd perl516/lib/perl5
find -name '*.pm' | xargs perl -MConfig -E'
   for (@ARGV) {
      s!^\./!!;
      s!^5\.\d+\.\d+/!!;
      s!^x86_64-linux/!!;
      s!^auto/!!;
      s!\.pm\z!!;
      s!/!::!g;
      say;
   }
' | xargs cpan

(做一个干跑 - 一个没有尾随| xargs cpan - 首先。)

请注意,如果您不希望受到管理员升级的支配,可以使用perlbrew在家庭目录中轻松安装整个Perl版本。

答案 1 :(得分:2)

如果您使用cpanm,可以使用local::lib-L开关强制它在--reinstall位置重建模块:

list_modules | cpanm -L ~/perl5 --reinstall

其中list_modules是一个脚本,用于将模块名称提供给cpanm-f的{​​{1}}选项也是cpanm。这个脚本可能就像上面的@ ikegami或cpan-outdated之类的东西(但只列出了过时的模块)。这里有一个 最近主要为我工作的hackish尝试(注意:ikegami可能更好) - 当它失败或脚本给cpanm一个模块名称时它无法识别,cpanm保持去,并没有打破任何东西(但做备份):

cd $PERL_LOCAL_LIB_ROOT  
perl -MFile::Find -MConfig -E'
      find { 
        wanted => sub { 
                       $mod = $_ if /\.pm\z/; 
                       $mod =~ s/lib\/perl5\/auto\/.*//g;
                       $mod =~ s/lib\/perl5\/\Q$Config{archname}\E\/.*//g;
                       $mod =~ s/lib\/perl5\///g;
                       push @mods, $mod unless $mod =~ /^$/;
                      },no_chdir=>1 
           },"lib/perl5"; @modhash{@mods}=(); say for sort keys %modhash '

通过使用File::Find更改wanted()找到的位置和内容,您可以将不同的模块列表提供给cpanm。如果cpancpanm有内部_method-switch允许您强制重建local::lib已安装的使用XS的模块,那就太好了。有这样的事吗?

cpanmcarton(看到node.js工具npm正在行动中)激励我做更多基于local::lib的安装。现在CORE捆绑了" CPAN客户端"与perl(cpan)一起发布的似乎越来越自动化,也越来越容易使用。我非常喜欢local::lib,因为它允许您使用系统perl,但管理您自己的模块堆栈而没有系统级权限。但是,如果您使用perlbrew运行非系统"则可以更轻松地管理更改和升级。 ("本地")perl。当然,你可以这样做仍然有local::libcarton 。管理目录或特定于应用程序的模块堆栈。

1)。另一种升级方法是使用perllocal生成当前安装的模块列表( NB 我不完全确定perllocal.pod是否保留在可靠/有用的状态)。 [编辑>实际上perllocal会保留已安装模块的历史记录,而不是当前安装的列表。您将要过滤此内容,或者您​​将最终重新安装整个系列的模块版本!)。此perlmonks节点显示了如何清理perllocal.podhttp://www.perlmonks.org/?node_id=483020。我更喜欢保留历史。]

要解析perllocal.pod以获取cpanm的输入,请搜索文件并将匹配项保存在数组中,然后将它们拆分为两个以从数组元素创建哈希值({ {1}})。更新的安装和版本号在文件中较低,因此您可以创建一个带有模块名称作为键的哈希值,并通过以后的条目更新值:

key,value,key,value

(注意:这不会进行错误检查 - perl -ne 'push @arr, grep {defined} (/\A=head2.*:\s+C<Module>\s+L<(.*)\||.*C<VERSION:\s(.*)>\Z/msx); }{ %h = map{ split/,/,$_,2 } @arr; print "$_\@$h{$_}\n" for keys %h' perllocal.pod 中的条目偶尔会缺少perllocal.pod数据和其他奇怪的内容,所以要小心。)

2)。 但是这个方法与ilmari在IRC上的#perl-help中提到的shell脚本相比相形见绌。它用 jq - 您真正需要的命令行实用程序(此后您将需要更多)。如果您使用cpanm安装模块,则会创建VERSION个文件。您可以利用该列表将列表提供给install.json以重新安装当前的模块集:

cpanm

非常快速,非常简单,您可以将其与 find ~/perl5/ -name install.json -exec jq '.name + "@" + .version' {} + 方法结合使用cpanm进行自我安装以重建模块。

3)。如果您使用curl来管理perl安装,则可以easily copy and reinstallperlbrew个版本到另一个版本的所有模块。

HTH!