我一直在使用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目录并从头开始重新安装所有模块(可能会遗漏一些,因为我无法记住它们)?
答案 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
。如果cpan
或cpanm
有内部_method
或-switch
允许您强制重建local::lib
已安装的使用XS的模块,那就太好了。有这样的事吗?
cpanm
,carton
(看到node.js
工具npm
正在行动中)激励我做更多基于local::lib
的安装。现在CORE捆绑了" CPAN客户端"与perl(cpan
)一起发布的似乎越来越自动化,也越来越容易使用。我非常喜欢local::lib
,因为它允许您使用系统perl
,但管理您自己的模块堆栈而没有系统级权限。但是,如果您使用perlbrew
运行非系统"则可以更轻松地管理更改和升级。 ("本地")perl
。当然,你可以这样做和仍然有local::lib
,carton
等。管理目录或特定于应用程序的模块堆栈。
1)。另一种升级方法是使用perllocal
生成当前安装的模块列表( NB 我不完全确定perllocal.pod
是否保留在可靠/有用的状态)。 [编辑>实际上perllocal
会保留已安装模块的历史记录,而不是当前安装的列表。您将要过滤此内容,或者您将最终重新安装整个系列的模块版本!)。此perlmonks节点显示了如何清理perllocal.pod
:http://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 reinstall从perlbrew
个版本到另一个版本的所有模块。
HTH!