查看Perl模块安装路径
2010-07-05 20:47:43 阿炯

查看perl模块使用的默认位置

可以使用'perl -V'可以查看@INC中的默认路径。
debian:~# perl -V
Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
Platform:
osname=linux, osvers=2.6.30.5-dsa-amd64, archname=x86_64-linux-gnu-thread-multi
......
Built under linux
Compiled at Aug 28 2009 22:24:50
@INC:
/etc/perl
/usr/local/lib/perl/5.10.0
/usr/local/share/perl/5.10.0
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.10
/usr/share/perl/5.10
/usr/local/lib/site_perl

----------------------------------------------------
hto@debian:~$ activeperl/bin/perl -V
Summary of my perl5 (revision 5 version 10 subversion 1) configuration:

Platform:
osname=linux, osvers=2.6.8-24.25-default, archname=x86_64-linux-thread-multi
......
Built under linux
Compiled at Jan 26 2010 21:05:45
@INC:
/opt/ActivePerl-5.10/site/lib
/opt/ActivePerl-5.10/lib
.


@INC 是perl 的一个特殊列表标量,他储存着你当前版本的Perl模块的路径。编译时,Perl会根据@INC存储的路径去查询用户所调用的模块。具体的是那些目录。通过命令行键入'perl -V' 来查看,我们同样可以再BEGIN代码块里对这个@INC进行操作。可以看到Perl会从这5个目录下面去找模块,其中”.”代表当前目录下。

%INC
当Perl程序中调用的文件或模块被找到后,Perl会叫这些信息存放在%INC这个哈希中去,其中的key为模块的名字,value为模块完整的路径名。试着看一下有哪些模块被用到了:
$ perl -MData::Dumper -le 'print Dumper(\%INC)';

----------------------------------------------------
将Perl安装到非默认路径的方式
perl Makefile.PL PREFIX=/lib/perl/path

Perl非默认路径模块的引用:

Perl:
use lib '/lib/perl/path';

Shell:
export PERLLIB=$PERLLIB:/lib/perl/path

可以通过修改Config.pm文件中的路径卸载相关模块:
/usr/share/kernel-package/Config/config.pmac
/usr/share/perl5/Debconf/Config.pm
/usr/share/perl/5.10.0/CPAN/HandleConfig.pm
/usr/share/perl/5.10.0/Log/Message/Config.pm
/usr/share/perl/5.10.0/Net/Config.pm
/usr/share/perl/5.10.0/ExtUtils/MakeMaker/Config.pm
/usr/share/perl/5.10.0/Module/Build/Config.pm
/usr/share/perl/5.10.0/CPANPLUS/Config.pm
/usr/lib/perl/5.10.0/Encode/Config.pm
/usr/lib/perl/5.10.0/Config.pm
-----------------------------
/opt/ActivePerl-5.10/lib/Encode/Config.pm
/opt/ActivePerl-5.10/lib/CPAN/HandleConfig.pm
/opt/ActivePerl-5.10/lib/CPAN/Config.pm
/opt/ActivePerl-5.10/lib/ActivePerl/Config.pm
/opt/ActivePerl-5.10/lib/Log/Message/Config.pm
/opt/ActivePerl-5.10/lib/Net/Config.pm
/opt/ActivePerl-5.10/lib/HTTP/Config.pm
/opt/ActivePerl-5.10/lib/ExtUtils/MakeMaker/Config.pm
/opt/ActivePerl-5.10/lib/Module/Build/Config.pm
/opt/ActivePerl-5.10/lib/CPANPLUS/Config.pm
/opt/ActivePerl-5.10/lib/Tkx/MegaConfig.pm
/opt/ActivePerl-5.10/lib/Config.pm

在perl脚本中使用非标准路径库的方法:

1、所编写的脚本需要在其中使用某一个库,这个库不在这个标准路径中
方法1:
使用perl的lib模块,在自己的脚本中的开头加如下行:
use lib qw(/home/hto/lib/perl5/5.10.0/
/home/hto/lib/perl5/site_perl/5.10.0
/home/hto/lib/perl5/site_perl
);


方法2:
直接修改@INC,在自己的脚本开头加如下行
BEGIN {
unshift @INC,
qw(/home/hto/lib/perl5/5.10.0/i386-linux
/home/hto/lib/perl5/5.10.0
/home/hto/lib/perl5/site_perl/5.10.0/i386-linux
/home/hto/lib/perl5/site_perl/5.10.0
/home/hto/lib/perl5/site_perl
);
}

2、需要安装一个模块A,模块A又依赖于模块B,但是B本身又不是安装在标准目录下;
这个时候再采取方法1可能就不是最好的方式了,可以设置perl的环境变量:
export PERL5LIB=/home/hto/lib/perl5/5.10.0:\ (注意是冒号)
/home/hto/lib/perl5/site_perl/5.10.0:\
/home/hto/lib/perl5/site_perl

若是要永久添加perl模块的安装目录,则修改PERL5LIB环境变量即可:
export PERL5LIB=/PATH/TO/LIB

以上说的都是perl脚本,如何引用非标准的库的位置的方法,那么在应用中具体应当怎么使用呢?
1)、在http.conf中设置如下行:
PerlSetEnv PERL5LIB /my/lib/perl:/other/lib/perl
举例来说,我们写了一个apache的mod_perl模块名字叫'httpd ::Hello.pm',这个模块的位置在:/home/hto/httpd/htdocs/lib/perl/httpd/Hello.pm
那么我们就有如下的配置:
PerlSetEnv PERL5LIB /home/hto/httpd/htdocs/lib/perl/

SetHandler perl-script
PerlHandler httpd::Hello


2)、还是上边的例子:
举例来说,编写了一个apache的mod_perl模块名字叫'httpd ::Hello.pm',这个模块的位置在:/home/hto/httpd/htdocs/lib/perl/httpd/Hello.pm
我们写了如下一个额外的脚本,命名为startup.pl
#/usr/bin/perl -w
use lib qw(/home/hto/httpd/htdocs/lib/perl/
);
1;#这个1是必须的

然后在httpd.conf中添加如下行
PerlRequire /home/hto/httpd/conf/startup.pl
PerlFreshRestart     On
SetHandler perl-script
PerlHandler httpd::Hello

然后重启相关的应用即可。

3、指定相关目录到'@INC'到当前脚本
perl - @INC doesn't include current directory

You may just "push" whatever dir you need to @INC.

BEGIN { push @INC,'.'; }

Or you add "." to the environment variable "PERL5LIB".

perl -e "print @INC;" and

perl -te "BEGIN { push @INC, '.'; } print @INC;"

Propably the taint-flags change the behavior (-t and -T) - compare the output of "perl -V" and "perl -Vt".

当开启'taint'模块时,对包含路径是有影响的。

查看系统中已经安装的Perl模块

这里介绍两种方法来查看已经安装的 Perl 模块,其中第一种方法通过文件名后缀识别 Perl 模块,该方法列出了所有安装的 Perl 模块(包括 Perl 的核心模块),而第二种方法只是列举了系统上安装的 CPAN Perl 模块。
---------------
Shell 脚本:
find `perl -e ‘print “@INC”‘` -name ‘*.pm’ -print

---------------
使用模块管理模块'ExtUtils'
use ExtUtils::Installed;
my $module;
my $inst = ExtUtils::Installed->new();
my (@modules) = $inst->modules();
foreach $module (@modules) {
  print "$module \n";
}

use ExtUtils::Installed;
my $inst = ExtUtils::Installed->new();
my @modules = $inst->modules();
foreach $module (@modules){
 print $module ." - ". $inst->version($module). "\n";
}

foreach (@modules) {
 my $ver = $inst->version($_) || "???";
 printf( "%-12s — %s\n", $_, $ver );
}

或单行操作:
perl -MExtUtils::Installed -MData::Dumper -e  'my ($inst) = ExtUtils::Installed->new();print Dumper($inst->modules());'

---------------
使用'instmodsh'指令来列出安装过的模块(List installed perl module)
$ instmodsh
Available commands are:
l            - List all installed modules
m    - Select a module
q            - Quit the program
cmd?

使用'l'指令来列出已安装的Perl模块。

---------------
直接使用'perl'指令来验证具体模块是否安装
取模块的'version'能否成功
perl -MCGI -e'print $CGI::VERSION'

模块安装好的话,会打出其当前版本,否则会报错。

---------------
使用'perldoc'指令查看具体模块的名称
perldoc perlmodlib

'perldoc perlmodlib' list the modules that come preinstalled with the standard perl package.

---------------
第三方模块:
使用'App-Module-Lister'模块

App::pmodinfo

---------------
第三方发行版本里的工具
If you use ActivePerl (very likely if you're using Perl in Windows), you may use the following command to obtain the list of modules:
ppm query


查看已安装的Perl模块:
# 查看系统中安装的Perl模块
find  `perl -e 'print "@INC"'` -name '*.pm'

查询单个perl模块的安装路径:
perldoc -l Getopt::Long

查看安装的perl模块的版本号
perl -MGetopt::Long -e 'print Getopt::Long->VERSION. "\n"'

装Perl模块通常有两种方法

自动安装 (使用CPAN模块自动完成下载、编译、安装的全过程);
手工安装 (去CPAN网站下载所需要的模块,手工编译、安装)。

非root用户可手动下载local::lib这个perl模块,然后自己安装在指定目录即可:
perl Makefile.PL --bootstrap=~/.perl ##这里设置想把模块放置的目录
make test && make install
echo 'eval $(perl -I$HOME/.perl/lib/perl5 -Mlocal::lib=$HOME/.perl)' >> ~/.bashrc ##目录与前面要一致

添加好环境变量之后,就可以用:
perl -MCPAN -Mlocal::lib -e 'CPAN::install(LWP)'

或:
cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)


----------------------------------------------------
use加载模块

安装模块后,都会有对应的文档,可以通过perldoc MODULE_NAME来获取模块的使用帮助。

例如:获取File::Utils的使用帮助:
perldoc File::Utils

要在perl程序中使用模块,需要使用use来装载(load)模块。例如File::Basename模块:
#!/usr/bin/perl
use File::Basename;

一般来说,所有要装载的模块都会写在perl程序的开头,因为use语句是程序编译期间执行的,而且以后要查看、修改程序中使用的模块也方便。当然这并非必须,可以在任意地方书写use语句。

装载模块后,模块内的属性就会导入到当前程序的名称空间供当前程序使用。例如File::Basename模块提供的两个子程序是basename()和dirname(),他们分别获取给定文件路径的basename和dirname。

#!/usr/bin/perl
use File::Basename;
my $basename = basename( "/usr/bin/perl" );
my $dirname = dirname( "/usr/bin/" );
print "$basename\n$dirname";

或者,只导入给定的函数:
use File::Basename ('basename','dirname');

推荐直接用qw()列表的方式,即使只导入一个函数:
use File::Basename qw(basename dirname);

函数导入到当前名称空间后,模块中的函数可能会和当前程序文件中定义的同名子程序冲突。这时需要指定函数的全名:
my $dirname = File::Basename::dirname("/usr/bin/");

如果导入模块时给出一个空列表,它和不给列表是不一样的。也就是说下面两种方式是不等价的:
use File::Basename;
use File::Basename ();

前者表示导入模块的默认属性,包括一些默认函数。而后者表示什么都不导入,这时如果要使用这个模块中的函数,只能使用全名。

另外有些模块比较复杂,函数、属性、方法比较多,一般这时候会提供标签分组功能,其实它们是一堆函数集合。这样可以在导入的时候按照分组标签来导入。常见的一个标签是:all,它表示导入所有属性。

use CGI qw(:all);

如果模块还提供了一个名为tag的标签,那么可以导入这个标签:
use MODULE_NAME qw(:tag);

想要知道模块是否提供了标签,以及提供了哪些标签,可以man MODULE获取。例如,CGI模块的man CGI文档中有一段内容如下:

Here is a list of the function sets you can import:

:cgi
Import all CGI-handling methods, such as param(), path_info() and the like.

:form
Import all fill-out form generating methods, such as textfield().

:html2
Import all methods that generate HTML 2.0 standard elements.

:html3
Import all methods that generate HTML 3.0 elements (such as <table>, <super> and <sub>).

:html4
Import all methods that generate HTML 4 elements (such as <abbrev>, <acronym> and <thead>).

:netscape
Import the <blink>, <fontsize> and <center> tags.

:html
Import all HTML-generating shortcuts (i.e. 'html2', 'html3', 'html4' and 'netscape')

:standard
Import "standard" features, 'html2', 'html3', 'html4', 'form' and 'cgi'.

:all
Import all the available methods.  

----------------------------------------------------
模块查找路径和@INC

默认情况下,perl将从@INC指定的路径中查找模块,它就像shell的PATH环境变量一样。以下是@INC的路径:
# perl -e 'foreach (@INC){print "$_\n"};'
/etc/perl
/usr/local/lib/x86_64-linux-gnu/perl/5.32.1
/usr/local/share/perl/5.32.1
/usr/lib/x86_64-linux-gnu/perl5/5.32
/usr/share/perl5
/usr/lib/x86_64-linux-gnu/perl-base
/usr/lib/x86_64-linux-gnu/perl/5.32
/usr/share/perl/5.32
/usr/local/lib/site_perl

如果手动安装的包,或者安装到了一个非默认的查找路径下(例如不同用户安装到了不同家目录下),这时可以通过在shell中设置PERL5LIB环境变量,perl会临时从这个环境变量中去查找模块。
# export PERL5LIB="/home/freeoa/myperl"

或者在perl命令行中使用-I选项,显式指定待运行程序的模块查找路径。
# perl -I/home/freeoa/myperl PERL_PROGRAM

还有几种更复杂的方法:
(1).在perl程序中,在use引用模块之前,使用BEGIN {unshift @INC,"/home/freeoa/myperl"};语句,使得@INC在编译期间就加上指定的查找目录
(2).在perl程序中,在use引用模块之前,使用use lib "/home/freeoa/myperl";指定lib查找路径

由于这些方法都不方便,所以直接设置PERL5LIB环境变量,或者设置local::lib即可。

更多关于Perl模块的安装及维护,请参考:从cpan上安装perl模块

----------------------------------------------------
Perl Core Modules

查看模块是否包含在Perl核心模块中
What modules are included in the Perl Core

"Core"模块只是一个约定的简短叫法,正式称为Perl标准发行版(完整的发行套件中就必须带有这些模块集),但在不同的操作系统发行版本中也略有不同。

来自Module::CoreList模块的corelist命令将确定指定的模块是否为Core。Module::CoreList从v5.9.4起成为Perl标准库的一部分。也可以在bash中直接运行命令corelist来查找和获取。
$ corelist -a Module::CoreList

Data for 2021-01-23
Module::CoreList was first released with perl v5.8.9
...

$ corelist -a JSON

Data for 2021-01-23
JSON was not in CORE (or so I think)

官方主页的参考文档(perldoc.perl.org)中有模块列表(https://perldoc.perl.org/modules)。在终端中查看本机所安装的各个模块基本信息。

通过使用模块来发现对应的模块是否在Core中。
use Module::CoreList;

my $mod = 'Carp';
#my $mod = 'XML::Twig';
my @ms = Module::CoreList->find_modules(qr/^$mod$/);
if(@ms){
    print "$mod in core\n";
}else{
    print "$mod not in core\n";
}

#===============================
use v5.32;

my %_stdmod;

sub is_standard_module {
  my($module) = @_;
  unless (keys %_stdmod) {
    chomp(my $perlmodlib = `perldoc -l perlmodlib`);
    die "cannot locate perlmodlib\n" unless $perlmodlib;

    open my $fh, "<", $perlmodlib
      or die "$0: open $perlmodlib: $!\n";

    while (<$fh>) {
      next unless /^=head\d\s+Pragmatic\s+Modules/ .. /^=head\d\s+CPAN/;

      if (/^=item\s+(\w+(::\w+)*)/) {
        ++$_stdmod{ lc $1 };
      }
    }
  }

  exists $_stdmod{ lc $module } ? $module : ();
}

die "Usage: $0 module..\n" unless @ARGV;

foreach my $mod (@ARGV) {
  my $stdmod = is_standard_module $mod;
  print "Module:$mod is ", ($stdmod ? "" : "not "), "Core\n";
}

>
perl coremod2.pl threads CGI Archive::Tar LWP List::Util

Module:threads is Core
Module:CGI is not Core
Module:Archive::Tar is Core
Module:LWP is not Core
Module:List::Util is Core

perldoc无疑是Perl真正核心和标准安装的一部分。例如,第5.10.1版本源就包含了:
perldoc.PL:生成perldoc作为标准安装的一部分
perlmodlib.PL:生成perlmodlib.pod作为标准安装的一部分

这不是新添加的。从Perl5.6.0开始,将PerlModLib作为其真正核心的标准安装的一部分,不包含这些项目的安装是非标准的。如果提供商是非标准安装可能会破坏其他工作程序。

简单测试模块是否在本机系统中被安装(以Net::FTP为例):

perl -MNet::FTP -e 1
perl -MTie::Hash -e 1

如果它没有输出,那么它就被安装了。

使用Debian Linux的包管理器来安装标准perl模块:
$ apt-get --install-recommends install perl
dpkg-query -L perl | less


模块使用相关的路径知识可参考:

FindBin模块

理解use_require_do

local::lib模块



该文章最后由 阿炯 于 2024-04-10 21:49:54 更新,目前是第 2 版。