写在前面,最近由于项目的原因,遇到一处bug,折腾了三天,中间尝试了许多的方法,走过许多的弯路,都没有得到答案。最终在师兄的帮助下,“解决”了这个问题。再次,把这一路的尝试的过程,列出来,作为经验的总结。
我的错误的具体内容是:
/usr/bin/perl: symbol lookup error: /opt/perl5/lib/perl5/x86_64-linux-thread-multi/auto/List/Util/Util.so: undefined symbol: Perl_xs_handshake
Failed to run /home/xxzhang/workplace/software/Shimmer/shimmer.pl --counts!
这个问题,我在网上查到的最常见的解释是:
这种类型的错误通常发生在使用Perl的一个版本编译的二进制文件被不同版本的Perl使用时,系统调用时根据PATH默认先选用/usr/local/lib64/perl5,而该perl没有相关mysql module或module不完整。
参考链接:https://www.cnblogs.com/dzqk/archive/2018/01/08/8236627.html
作者给出的解决方案是修改,系统中默认调用的perl的地址名。
mv /usr/local/lib64/perl5 /usr/local/lib64/perl5_drop
但是,由于我自己是非root用户,所以没有权限修改这个地址的名字。所以,这个解决的思路,并不是适用于我的个人的情况。
接下来,我主要进行了两个方面的尝试。
(1)首先,我在服务器上,使用服务器用户路径下的perl程序,重新编译安装了shimmer的安装包。===>最后依旧是报同样的错误。
(2)其次,我修改了shimmer.pl这个文件的第一行,默认的“#!usr/bin/perl”,将其修改为我编译所使用的perl的路径“#!/home/xxzhang/miniconda/bin/perl”(这个操作可能是解决问题的重点)
关于“#!usr/bin/perl”的解释是这样的。刚开始的时候,我没有想到这行注释会具有如此重要的意义。它主要的意思就是说,规定这个perl文件,运行的perl的路径在什么地方。所以,毫无疑问的,在运行我们的perl文件的时候,系统会默认去找这里的perl路径,以及其所附属的环境便量的配置。由于各种不可控的原因,这里的perl缺这少那,且我们无法调整。
所以,解决方案就是,修改这行默认的注释行(它又是必须的,否则会爆其他的错误),将其替换为我们的可控的perl的路径即可。
另外,我在这个过程中,也遇到了杂七杂八的与perl的环境配置相关的指令,分享给大家。
perl -V
在它的最后,会显示:
@INC:
/etc/perl
/usr/local/lib/x86_64-linux-gnu/perl/5.26.1
/usr/local/share/perl/5.26.1
/usr/lib/x86_64-linux-gnu/perl5/5.26
/usr/share/perl5
/usr/lib/x86_64-linux-gnu/perl/5.26
/usr/share/perl/5.26
/usr/local/lib/site_perl
/usr/lib/x86_64-linux-gnu/perl-base
这里的@INC,就是perl的lib库所在的位置。按照排列的前后,会有一个调用的优先级。我们希望,一些安装的模块,会存在这些路径下,否则系统会报出模块缺失的错误。
怎么检查模块是否有安装?
输入:perl -MMail::Sender
如果屏幕显示如图,则模块未安装(或者安装了,却不再我们的@INC路径中,需要额外添加路径信息)。
Can’t locate Mail/Sender.pm in @INC (you may need to install the Mail::Sender module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.26.1 /usr/local/share/perl/5.26.1 /usr/lib/x86_64-linux-gnu/perl5/5.26 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.26 /usr/share/perl/5.26 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base).
BEGIN failed–compilation aborted.
如何安装perl中的模块呢?
一般而言,如果我们系统中有安装有conda,比较推荐的一种方式是,使用conda直接安装。因为如果,你没有root权限的话,一般需要手动安装一些模块,去conda的官网上按照一些关键词搜索,不一定能够找到完全匹配的。而使用conda安装的话,则相对比较简单(傻瓜式的)。
参考链接:https://xw.qq.com/cmsid/20210219A09M3R00
比如,如果我们想要安装Module::Build这个模块,使用conda就可以直接运行指令:
conda install -c bioconda perl-module-build
默认的安装路径在,conda的pkgs的文件夹下,具体需要自己去摸索。如前面的例子,模块build.pm一般是在module文件夹下。
接下来,遇到的一个问题,如何告诉计算机,你安装好的.pm文件的位置,让他找到,并执行呢?这里就需要设置,PERL5LIB参数。
我们只需要将我们模块所在的路径,添加到PERL5LIB变量中即可。如:
export PERL5LIB=/home/xxzhang/miniconda/pags/:$PERL5LIB
如果想要查看目前系统中的$PERL5LIB,可以:
echo $PERL5LIB
另外,如果系统中存在多个perl版本,可以使用 local::lib模块进行路径的管理。这个模块,可以设置我们的优先使用的perl路径,关于这点,我自己了解的还不深刻,等有时间再认真研究一下。这次卡在了这个地方,着实苦涩,要把经历过的经验转化为一种前行的力量。
参考链接:https://www.cnblogs.com/f-ck-need-u/p/9685581.html
最后,师兄也推荐了一个perl路径管理的工具叫perlbrew,我也还没有进一步的研究这件事。