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

pwa*_*ing 13 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.
Run Code Online (Sandbox Code Playgroud)

我的理解是我可以通过强制local :: lib来重建它的所有模块来修复这个问题,但我在文档中找不到任何告诉我如何做到这一点的内容,甚至找不到如何获取所有模块的列表.使用local :: lib安装的模块(如果我在"每行一个模块"文本文件中有这个模块,我可以轻松编写一个Bash脚本来处理它).

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

G. *_*ito 7

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

list_modules | cpanm -L ~/perl5 --reinstall

其中list_modules是一个将模块名称提供给 的脚本cpanm(还有一个-f选项cpanm)。该脚本可能类似于@ikegami 上面的脚本或类似的脚本cpan-outdated(但仅列出过时的模块)。这是一个最近对我有用的黑客尝试(注意:池上的可能更好) - 当它失败或脚本给出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 '
Run Code Online (Sandbox Code Playgroud)

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

正是cpanmcarton并看到该node.js工具npm的实际应用)激励我进行更多local::lib基础安装。现在,与 perl () 一起提供的 CORE 捆绑的“CPAN 客户端”cpan似乎变得更加自动化并且也更易于使用。我真的很喜欢local::lib,因为它允许您使用系统perl,但无需系统级权限即可管理自己的模块堆栈。perlbrew但是,如果您用于运行“非系统”(“本地”),则总体上管理更改和升级会更容易perl。当然,您可以这样做,并且仍然local::lib可以carton 等等。管理目录或应用程序特定的模块堆栈。

1)。进行升级的另一种方法是使用perllocal生成当前安装的模块的列表(注意,我不完全确定是否perllocal.pod保持可靠/有用的状态)。[编辑:事实上,perllocal保留已安装模块的历史记录,而不是当前已安装模块的列表。您需要过滤掉这个,否则您最终将一个接一个地重新安装整个系列的模块版本!)。此 perlmonks 节点展示了如何清理您的perllocal.pod:http://www.perlmonks.org/?node_id=483020。我更喜欢保留历史。]

perllocal.pod解析 的输入cpanm,请搜索将匹配项保存在数组中的文件,然后将它们一分为二以根据数组元素创建哈希 ( 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
Run Code Online (Sandbox Code Playgroud)

(注意:这不会进行错误检查 - 条目perllocal.pod有时会缺少VERSION数据和其他奇怪的情况,所以要小心。)

2)。与 ilmari 在 IRC 上的 #perl-help 中提到的 shell 脚本相比,这种方法就显得苍白无力了。它使用 - 一个您真正需要的jq命令行实用程序(此后您会更需要它)。如果您曾经安装过模块,它将创建文件。您可以利用它来创建列表以重新安装当前的模块集:cpanminstall.jsoncpanm

 find ~/perl5/ -name install.json -exec jq '.name + "@" + .version' {} +
Run Code Online (Sandbox Code Playgroud)

非常快,非常简单,您可以将它与cpanm使用curl自安装的方法结合起来重建您的模块。

3)。如果您用来perlbrew管理 Perl 安装,您可以轻松地将所有模块从一个版本复制并重新安装perl到另一个版本。

哈!


ike*_*ami 6

更新:一段时间以来,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
Run Code Online (Sandbox Code Playgroud)

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

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

  • +1提及:`由install :: lib sucks`使用:) (2认同)