我这个周末早些时候安装了Ubuntu,并且必须为我正在使用的脚本安装perl(5.22.0)的更新版本。 但是,当我使用CPAN安装我需要的模块时,我发现它们已经安装在Ubuntu的默认perl(5.18.2)中。 我运行perl -l ,显示更新后的perl5,但由于某种原因CPAN拒绝使用它。
我确定它是一个configuration问题,或者我误解了CPAN的工作原理。 无论哪种方式,我已经浏览了谷歌的网页和页面试图find解决scheme无济于事。 我希望这里有人能指导我正确的方向,也许这可以帮助其他有类似问题的人。
我有完全一样的问题。 警告:我使用的是Fedora。 但是,fc22打破了我的perl脚本[perl 5.20.3解释器会segfault],所以我不得不安装5.22.0,所以我有一些直接的经验。
找出新的解释器的configuration
首先,你如何安装。 我猜你使用安装程序来安装5.22.0的二进制包。 这是否覆盖/usr/bin/perl ? 我假设如此。 或者,它被安装为(例如) /usr/bin/perl-5.22.0 ?
在/usr/lib64/perl/Config.pm ,查看底部find并列散列。 这将有configuration。 另一个[也许更好]的方法是将@INC转储出来并use Config; 并从[perl]脚本中转储Config哈希。
特别感兴趣的是privlibexp , sitearchexp , sitelibexp和archlibexpvariables。
倾销@INC是最@INC的。
注意/回答的问题是:5.22.0 perl解释器是使用5.22.0目录还是一些configuration仍然指向5.18.2?
在一个或多个这些目录下应该是CPAN.pm以及CPAN子目录。 我的猜测是你只能在5.18.2的相关目录下find它。
事实上,经过一番调查,你会发现你现在有一个“混合”的安装,既不是5.18.2也不是5.22.0。 如果您[决定]遵循我的“推荐最佳实践”[见下文],则可能希望卸载5.22.0,以便安装库存/标准5.18.2。 如果Ubuntu确实发布了一个补丁,这可以最大限度地减less头痛
一点关于CPAN
当一个发行版安装perl软件包,可以从CPAN得到的软件包重叠 ,它可以工作,sorting。 但是,实际上,他们经常发生冲突。 而且,对发行版使用非标准的perl版本需要更多的关注。
您可能需要使用新的解释器在5.22.0目录下安装CPAN。 这可能是简短的答案。
所以这就提出了CPAN如何安装的问题。 它是来自发行版还是手动安装? 如果从发行版,“升级”可能工作。 否则,请从新的perl解释器手动安装它 – 应该将它[和它安装的任何东西]发送到正确的位置。
另外,在$HOME你应该find一个.cpan目录[如果你已经运行]。 特别感兴趣的是$HOME/.cpan/CPAN 。 它应该有一个cpanconfiguration文件(例如$HOME/.cpan/CPAN/MyConfig.pm )。 有许多variables,但是make_install_make_command可能有一些用处
我所做的 – 推荐最佳实践
[注:我已经做了20 +的Perl – 我目前的脚本回购有25万行。
我不得不面对几个这样的问题。 坦率地说,我不会“发动”发行版了,因为你所遇到的问题。 尽pipe在纸面上,发行版声称可以同时安装多个软件包版本,但是我一直对这个perl特别是运气不好。
国际海事组织,根据我的经验,你遇到的问题只是冰山一angular。 即使你解决了,以后可能会有更多类似的问题。
如果我需要一个替代perl版本,我去perl网站,下载源码包并重build它。 注意:build议[来自perl网站]的build议是从perl网站下载源代码,而不是尝试从发行版软件包中重build。
我为./Configure脚本指定一个备用前缀,以便将所有内容放在新的位置。 然后,做一个make并make install 。
例如,我的5.22.0 perl位于/home/alt/perl/perl-5.22.0之下,它/home/alt/perl/perl-5.22.0有bin/perl , lib/CPAN.pm和lib/CPAN 。 我能够维护尽可能多的不同版本,因为它们都是/home/alt/perl/<version>
之后,我可以(例如): ln -sf /home/alt/perl/perl-5.22.0/bin/perl /usr/bin/perl22并更改我想用的脚本#!/usr/bin/perl22 。
这里是我用来configurationPerl的选项。 前三个是最重要的[*]:
-Dprefix=/home/alt/perl/perl-5.22.0 -Dstartperl=/home/alt/perl/perl-5.22.0/bin/perl -Dusethreads=y -DEBUGGING=both -Doptimize=-gdwarf-2 -Dman1dir=none [email protected] -Dpager=/usr/bin/less '-Dstatic_ext=threads threads/shared' -d -e -s
请注意,因为Fedora的5.20.3有问题,所以我可能会添加一些额外的debugging选项。
如果你想要一个私人的/实验的副本,另一个地方是/ /home/myself/perl/perl-5.22.0 / /home/myself/perl/perl-5.22.0 / /home/myself/perl/perl-5.22.0 / /home/myself/perl/perl-5.22.0 。
注意:因为我用了一个完全不同的地方来安装5.22.0,5.22.0和5.20.3 并存的完全和谐。 他们不以任何方式干涉[AFAICT]。
你甚至可以尝试一下, 而不会干扰你已经安装的5.22.0。
我的实际重build脚本
[PS]当然,我有一个完全自动化的Perl脚本来完成所有这些configuration,构build,安装[并从网站拉取tarball]
这些将不可运行,因为它们需要/承担很多我现有的基础设施。 他们仅仅是一个松散的参考。 如果你关心所有,忽略你不能立即认识的99.44%。
这里是perl特定的脚本:
#!/usr/bin/perl # altbld/qprlmkx -- connect to CPAN # # xperl -- execute script with alternate perl interpreter # "-b" -- use base script name (eg skip XBIN) # "-ddd" -- run ddd on perl # "-db" -- run perl script debugger (perl's -d) # "-D" -- perl -D options (see perlrun manpage) # "-E" -- environment variables # "-Lc" -- use alternate glibc (BROKEN) # "-Ld" -- set up PERLIO_DEBUG # "-Le" -- force glibc to use stderr for fatal errors # "-S" -- do vxshazam (recommended for debug on vxshazam programs) # # pathx -- dump the path # # qprlmkc -- configure perl interpreter # qprlmkx -- remake perl interpreter use qslib::qsinit; use qpile::qpchk; use qsnet::rshlib; use pjx::pjxlib; use qpile::qploc; use altbld::altlib; use gtx::gtxlib; master(@ARGV); exit(0); # master -- master control sub master { my(@argv) = @_; my($proc); my(@opts); unshift(@argv,"-ddd") if ($pgmtail eq "qprlgdb"); while (1) { vbqdash(\@argv); vbqnumdcd($_,"-S",1,\$keyS); vbqnumdcd($_,"-go",1,\$keygo); if (($pgmtail eq "xperl") || ($pgmtail =~ /^tskdir/)) { vbqnumdcd($_,"-b",1,\$keyb); vbqnumdcd($_,"-db",1,\$keydb); vbqvstrdcd($_,"-D","tlsRSD",\@keyD); vbqvstrdcd($_,"-E",undef,\@keyE); vbqnumdcd($_,"-Le",1,\$keyLe); vbqnumdcd($_,"-Lc",1,\$keyLc); vbqnumdcd($_,"-Ld",1,\$keyLd); pjxdddopt($_); vbqnumdcd($_,"-help",1,\$keyhelp); vbqnumdcd($_,"-Q",1,\$keyQ); vbqnumdcd($_,"-S",1,\$keyS); } if ($pgmtail eq "qprlmkc") { vbqvstrdcd($_,"-D",undef,\@keyD); vbqnumdcd($_,"-publish",1,\$keypublish); } vbqnumdcd($_,"-ask",1,\$keyask); vbqnumdcd($_,"-sh",1,\$keysh); altoptdcd($_); sysusage($_); } vxshazam() if ($keyS); push(@opts,"-V$keyV") if ($keyV ne ""); $APL = altverget(@opts,"perl"); $ALTPERL = $APL->{alt_xfile}; $APL->{alt_bld} = $APL->{alt_src}; $APL->{alt_remhost} = "ftp.cpan.org"; $APL->{alt_remtop} = "pub/CPAN/src"; ###$APL->{alt_remdir} = "/gcc-" . $APL->{alt_revuse}; $APL->{alt_remsuf} = ".tar.gz"; $proc = "cmd_" . $pgmtail; &$proc(@argv); } # cmd_qprlwget -- pull perl sub cmd_qprlwget { altwget($APL); } # cmd_qmetacfg -- pull perl sub cmd_qmetacfg { my($sdir); my($tail); $sdir = $APL->{alt_top}; msg("$pgmtail: chdir %s ...\n",$sdir); xchdir($sdir); # get metaconfig { if (-d $tail) { msg("$pgmtail: project dir already exists\n"); last; } last; vxsystem("git","clone", "git://perl5.git.perl.org/$tail.git", $tail); } } # cmd_qprlver -- show versions sub cmd_qprlver { } # cmd_qprldis -- disassemble executable sub cmd_qprldis { vxsystem("-x","asmdis",$APL->{alt_xfile}); } # cmd_qprlmkc -- configure perl sub cmd_qprlmkc { my(@opts); my(@shopts); push(@lnklist); my($src,$ins,$bld,$xfile); my($tail,$lnkto); $keygo = 0 if ($keypublish); $src = $APL->{alt_src}; $ins = $APL->{alt_ins}; $bld = $APL->{alt_bld}; $xfile = $APL->{alt_xfile}; xchdir($src); ###sysrmdir($bld); ###xmkdir($bld); ###xchdir($bld); # make depend fails [due to bug] without some symlinks ###push(@lnklist,qw(makedepend.SH Makefile.SH perl_exp.SH config_h.SH)); foreach $tail (@lnklist) { $lnkto = "$src/$tail"; symlink($lnkto,$tail) || sysfault("qprlmkc: unable to symlink to '%s' -- $!\n",$lnkto); } # save us some complaints if ($keygo) { xmkdir($ins); xmkdir("$ins/bin"); } push(@opts,"-Dprefix=$ins"); push(@opts,"-Dstartperl=$xfile"); push(@opts,"-Dusethreads=y"); ###push(@opts,"-Duseithreads=y"); ###push(@opts,"-Duselargefiles"); ###push(@opts,"-Duse64bitall=y"); ###push(@opts,"-Dusedevel"); push(@opts,"-DEBUGGING=both"); push(@opts,"-Doptimize=-gdwarf-2"); ###push(@keyD,"DEBUG_LEAKING_SCALARS"); foreach $opt (@keyD) { push(@opts,"-A","ccflags=-D$opt"); } # hard to breakpoint on dynamically loaded stuff if (1) { push(@sext,"threads"); push(@sext,"threads/shared"); } push(@opts,"-Dman1dir=none"); $env = gtxconfig("user"); $email = $env->{email}; $email = "anybody\@gmail.com" if ($keypublish); push(@opts,"-Dcf_email=" . $email); if (0) { push(@opts,"-Dnetdb_host_type=const void *"); push(@opts,"-Dnetdb_hlen_type=socklen_t"); } push(@opts,"-Dpager=/usr/bin/less"); if (@sext > 0) { $opt = join(" ",@sext); push(@opts,"-Dstatic_ext=$opt"); } # NOTE: to use threads, one must also use perlio :-( ###push(@opts,"-Duseperlio=n"); ###push(@opts,$APL->{alt_src}); # whip through defaults push(@opts,"-d","-e","-s") unless ($keyask); msgv("$pgmtail: OPTS",@opts); if ($keypublish) { foreach $opt (@opts) { $opt = $quo_1 . $opt . $quo_1 if ($opt =~ /\s/); printf("%s\n",$opt); } } unless ($keygo) { sysfault("$pgmtail: rerun with -go to actually do it\n"); } sleep(5) if (sysisatty(1)); push(@shopts,"-x") if ($keysh); { last unless ($keygo); vxsystem("sh",@shopts,"$APL->{alt_src}/Configure",@opts); } # complains on the second round { last unless ($keygo); last if (-e "$src/MANIFEST_NOT"); msg("$pgmtail: renaming manifest ...\n"); rename("$src/MANIFEST","$src/MANIFEST_NOT"); $xfdst = xfopen(">$src/MANIFEST","qprlmkc"); $xfdst = xfclose($xfdst,"qprlmkc"); } } # cmd_qprlmkx -- make perl executable sub cmd_qprlmkx { my(@opts); xchdir($APL->{alt_bld}); vxsystem("-x","make"); } # cmd_xperl -- invoke alternate perl sub cmd_xperl { my(@argv) = @_; my(@opts); unshift(@argv,"-V") if ($keyQ); @opts = altperl(@argv); enveval("ALTPERL",$ALTPERL); { last if (defined($keyddd)); xperlenv(); exec($ALTPERL,@opts); sysfault("$pgmtail: exec of '%s' failed -- $!\n",$ALTPERL); } pjxgdbinit("-alien=$APL->{alt_src}",@opts); pjxdddloc(); xperlenv(); vxsystem("-x",@ddd,$ALTPERL); } # xperlenv -- set up environment sub xperlenv { my($opt); foreach $opt (@keyE) { if ($opt =~ /$keyval_rgx/o) { enveval($1,$2); } } } # altperl -- get alternate perl sub altperl { my(@argv) = @_; my(@keyD); local(@opts); my($tail,$file); my($logf); zprt(ZPXHOWEXEC,"altperl: ENTER\n"); zprtlist(ZPXHOWEXEC,"altperl/ARGV",\@argv); envchk(qw(XLBIN)); # turn on perl's internal tracing # NOTE: perl must be compiled with -DEBUGGING for this to work foreach $opt (@keyD) { push(@opts,"-D$opt"); $keyLe = 1; } # run the script debugger push(@opts,"-dt") if ($keydb); while (1) { vbqdash(\@argv); push(@opts,$_); zprt(ZPXHOWEXEC,"altperl: PUSHOPT '%s'\n",$_); } # locate the script { $tail = shift(@argv); $file = tstloc($tail); last if (defined($file)); if ($tail =~ m,^[./],) { $file = $tail; last; } # skip the XBIN entries and go direct to the final script if ($keyb) { $file = basescan($tail); last; } $file = "$XLBIN/$tail"; } push(@opts,$file); # tell tskdirbug to _not_ fork/exec { last unless ($keyddd || $keydb); last unless (defined($tst_xfile)); push(@opts,"-d"); } enveval("LIBC_FATAL_STDERR_",1) if ($keyLe); $keyLd = 1 if (zprtok(ZPXHOWGDB)); if ($keyLd) { $logf = logfile("qprldbg"); msg("altperl: PERLIO_DEBUG %s ...\n",$logf); unlink($logf); enveval("PERLIO_DEBUG",$logf); } # FIXME/CAE -- this needs work ###$glibc_ins = "/home/libc"; ###$dir = "$glibc_ins/lib"; ###enveval("LD_LIBRARY_PATH",$dir) ###if ($keyLc); push(@opts,@argv); msgv("altperl: OPTS",@opts,"..."); zprt(ZPXHOWEXEC,"altperl: EXIT\n"); @opts; } # basescan -- run perl debugger on base script sub basescan { my($basetail) = @_; my($topdir); my($basefile); my($bindir,@binpath); my($lnkfile); $topdir = syshome("altperl"); sysrmdir($topdir); xmkdir($topdir); @binpath = qpbinpath(); foreach $bindir (@binpath) { push(@opts,"-I$bindir"); } $basefile = qplocate($basetail); sysfault("basescan: unable to locate '%s'\n",$basetail) unless (-e $basefile); msg("basescan: %s --> %s ...\n",$basetail,$basefile); # we have to create a link with the correct command name in it $lnkfile = "$topdir/$basetail"; symlink($basefile,$lnkfile) || sysfault("basescan: unable to symlink '%s' to '%s' -- $!\n", $lnkfile,$basefile); $lnkfile; } # cmd_pathx -- show path sub cmd_pathx { my(@argv) = @_; # execute ourself with the alternate interpreter -- we will _not_ # recurse further because we're leaving off the -P { last if ($keyV eq ""); exec($ALTPERL,$0); sysfault("$pgmtail: exec failure -- $!\n"); } showpath("INC",\@INC); showpath("PATH"); showpath("LD_LIBRARY_PATH"); } # showpath -- show a path sub showpath { my($sym,$path) = @_; my(@path); printf("%s:\n",$sym); { if (ref($path)) { @path = @$path; last; } $path = $ENV{$sym}; @path = syspathsplit($path); } foreach $path (@path) { printf(" %s\n",$path); } } # cmd_tskdirbug -- wrapper for tskdirbug sub cmd_tskdirbug { my($xfile); $xfile = tstloc(); if ($keyhelp) { sysusage_less(pgmbase(),$xfile); } } # tstloc -- locate script sub tstloc { my($tail) = @_; my($code); my($xfile); $tail //= "tskdirbug"; $tst_top = cdxgo("cdt"); { if ($tail =~ /^tskdir/) { $tst_dir = "$tst_top/tskdirbug"; last; } $tst_dir = "$tst_top/$tail"; } $xfile = "$tst_dir/$tail"; undef($xfile) unless (-e $xfile); $tst_xfile = $xfile; { last if ($keyhelp); last unless (defined($xfile)); $code = qpchkgo($xfile); exit(1) if ($code); } $xfile; }
这是它的主库[这是build立其他东西的基础,如glibc,gcc等]:
# altbld/altlib.pm -- common alternate make control # #@+ # "-a" -- push all versions # "-go" -- actually do it (install) # "-j" -- suppress parallel build # "-url" -- output top url # "-V" -- target version to build (DEFAULT: highest) # "-x" -- extractable versions #@- _altsetup(); # _altsetup -- passive setup sub _altsetup { $altsuf{".tar.gz"} = "z"; $altsuf{".tgz"} = "z"; $altsuf{".tar.bz"} = "j"; $altsuf{".tbz"} = "j"; @altsuf = reverse(sort(keys(%altsuf))); } # altoptdcd -- decode options sub altoptdcd { my($arg) = @_; vbqnumdcd($arg,"-a",1,\$keya); vbqnumdcd($arg,"-go",1,\$keygo); vbqstrdcd($arg,"-install","",\$keyinstall); vbqnumdcd($arg,"-j",1,\$keyj); vbqstrdcd($arg,"-V","",\$keyV); vbqnumdcd($arg,"-x",1,\$keyx); vbqnumdcd($arg,"-url",1,\$keyurl); } # altwget -- get versions sub altwget { local($alt) = @_; local($remtop); local($foundcnt); my($rev,@revlist); sysfault("!altwget: bad pointer\n") unless (ref($alt)); # most sites allow ftp with some exceptions (eg python.org) $remtop = $alt->{alt_remproto}; $remtop //= "ftp"; $remtop .= "://" . $alt->{alt_remhost} . "/" . $alt->{alt_remtop}; { if ($keyurl) { printf("%s\n",$remtop); last; } if ($keya) { @revlist = @{$alt->{alt_revlist}}; last; } push(@revlist,$alt->{alt_revuse}); } foreach $rev (@revlist) { _altwget($rev); } } # _altwget -- pull version from website sub _altwget { my($rev) = @_; my($remurl,$remtail); my($tgzfile); my($dir,@dirs); my($subdir); my($cmd); $remurl .= $remtop; $remurl .= $alt->{alt_remdir}; $remtail = $alt->{alt_name} . "-$rev" . $alt->{alt_remsuf}; $remurl .= "/$remtail"; xchdir($alt->{alt_netsave}); $tgzfile = $alt->{alt_netsave} . "/$remtail"; { $cmd = $altsuf{$alt->{alt_remsuf}}; if (defined($cmd)) { $cmd .= "xf"; last; } sysfault("_altwget: unknown suffix -- %s\n",$remurl); } { # pull the file unless (-e $tgzfile) { msgv("altwget:",NOGO("pulling"),$remurl,"..."); if ($keygo) { $code = vxsystem("wget",$remurl); last if ($code); } } { ($dir) = homesrc("-d",$alt->{alt_name}); unless (defined($dir)) { msgv("altwget: no directory found --",@dirs); last; } zprtx("\n") if ($keya); $subdir = "$dir/" . $alt->{alt_name} . "-$rev"; if (-d $subdir) { msgv("altwget:",NOGO("removing"),$subdir); sysrmdir($subdir) if ($keygo); } msgv("altwget:",NOGO("extracting"),$rev,"in",$dir,"..."); $code = vxsystem("-C$dir","tar",$cmd,$tgzfile) if ($keygo); $foundcnt++; } unless ($keygo) { msg("altwget: rerun with -go to actually do it\n"); last; } } msg("altwget: %s\n",$code ? "errors" : "complete"); } # altverget -- get version sub altverget # "-ins" -- scan install directories # "-q" -- quiet mode { my(@argv) = @_; my($keyins,$keyq) = (0,0); my($keyV); my($svmsg); my($pjname); my($tail,@tails); my($dir,@dirs); my(@revlist); my($revfound); my($revuse); my($sym,$val); my($suf); my($alt); while (1) { vbqdash(\@argv); vbqnumdcd($_,"-ins",1,\$keyins); vbqstrdcd($_,"-V","",\$keyV); vbqnumdcd($_,"-q",1,\$keyq); vbqusage($_,"altverget"); } $svmsg = msgqtpush($keyq); $pjname = shift(@argv); msg("altverget: project %s ...\n",$pjname); $alt = {}; $alt->{alt_name} = $pjname; envchk(qw(NETSAVE)); $alt->{alt_netsave} = filejoin($NETSAVE,$pjname); msg("altverget: netsave %s ...\n",$alt->{alt_netsave}); $alt->{alt_ins} = "/home/alt/$pjname"; $revlist = []; $alt->{alt_revlist} = $revlist; { if ($keyins) { @dirs = ($alt->{alt_ins}); msg("altverget: from install ...\n"); last; } if ($keya) { $keyx = 1; } else { last if ($pgmtail =~ /wget/); } if ($keyx) { msg("altverget: from netsave ...\n"); @dirs = ($alt->{alt_netsave}); last; } msg("altverget: from src ...\n"); @dirs = homesrc($pjname); } foreach $dir (@dirs) { $alt->{alt_top} = $dir; $alt->{alt_src} = $dir; # get known versions if (-e $alt->{alt_src}) { @tails = xfdirload($alt->{alt_src},"altverget"); foreach $tail (@tails) { next unless ($tail =~ s/^$pjname-//); foreach $suf (@altsuf) { last if ($tail =~ s,$suf$,,); } push(@$revlist,$tail); } @$revlist = revsort(@$revlist); msgv("altverget: versions",@$revlist); $revfound = $revlist->[$#$revlist]; last; } } # do final selection on revision { { # explicit command line override if ($keyV ne "") { $revuse = $keyV; last; } # grab an override from the environment $sym = "ALTREV_" . $pjname; $val = $ENV{$sym}; if ($val ne "") { $revuse = $val; last; } $sym = "PJNAME"; $val = $ENV{$sym}; if ($val =~ s/^$pjname-//) { $revuse = $val; last; } # use searched for value $revuse = $revfound; } if ($revuse eq "") { $revuse = "unknown"; $alt->{alt_revuse} = $revuse; last if ($keyins); last if ($keyurl); sysfault("altverget: no version specified\n"); } msg("altverget: VERSION %s ...\n",$revuse); $alt->{alt_revuse} = $revuse; } $alt->{alt_src} .= "/$pjname-$revuse"; msg("altverget: source %s ...\n",$alt->{alt_src}); $alt->{alt_bld} = syshome("-xt","alt/build/$pjname/$pjname-$revuse"); msg("altverget: build %s ...\n",$alt->{alt_bld}); $alt->{alt_ins} .= "/$pjname-$revuse"; ###$alt->{alt_ins} .= "/$pjname"; msg("altverget: install %s ...\n",$alt->{alt_ins}); { if ($revuse eq "std") { $alt->{alt_xfile} = "/usr/bin/$pjname"; $alt->{alt_std} = 1; last; } $pjname =~ s/-.+$//; $alt->{alt_xfile} = $alt->{alt_ins} . "/bin/$pjname"; } msg("altverget: xfile %s ...\n",$alt->{alt_xfile}); msgqtpop($svmsg); $alt; } 1;