+ -
当前位置:首页 → 问答吧 → 一个安装cpan模块的脚本

一个安装cpan模块的脚本

时间:2010-09-10

来源:互联网

CPAN命令好像是用Net::FTP来获取下载地址的,但是我的ftp端口被禁了,所以不能用cpan命令来安装了,不过http端口可以用,以前都是一个一个下载安装,最近觉得有必要自己写一个自动安装的脚本。 到目前为止还比较好使,大家感兴趣的可以试一下
  1. #!/usr/local/bin/perl5

  2. use warnings;
  3. use strict;

  4. use WWW::Mechanize;
  5. use HTML::TreeBuilder;
  6. use HTML::Query 'query';
  7. use Cwd;
  8. use File::Basename;

  9. die "Usage: $0 module_name\n" unless @ARGV;
  10. my ($module) = @ARGV;

  11. my $prefix  = "~/perl5";
  12. my $tmp_dir = "~/test";
  13. my $http_proxy = "http://proxy.com:80";

  14. my $mech = WWW::Mechanize->new(autocheck=>1);
  15. $mech->stack_depth(0);
  16. $mech->proxy(['http'], $http_proxy) if (! $ENV{http_proxy});

  17. print "you want to install $module...\n";
  18. &install($module);

  19. ###########################
  20. sub get_url_from_cpan {
  21.     my $module = shift;
  22.     my $cpan_url = "http://search.cpan.org";
  23.     print "get search_page ...\nurl=$cpan_url\n";
  24.     # search the module in CPAN main page
  25.     $mech->get($cpan_url);
  26.     $mech->set_fields(query => $module);
  27.     $mech->submit();
  28.     my $search_page_content = $mech->content();

  29.     # parse the search page to find the url of this module
  30.     my $tree = HTML::TreeBuilder->new;
  31.     my $success = $tree->parse($search_page_content);
  32.     $success    = $tree->eof();
  33.     die "parse search_page_content failed: $!\n" unless $success;

  34.     my $h2s = $tree->query('h2.sr'); #<h2> with sr class
  35.     my $href;
  36.     for my $h2 (@$h2s) {
  37.         my $module_name = $h2->query('a[href]')->as_trimmed_text->[0];
  38.         print "module_name: $module_name, module: $module\n";
  39.         if ($module_name eq $module) {
  40.             $href = $h2->query('a[href]')->attr('href')->[0];
  41.             last;
  42.         }
  43.     }

  44.     # fetch the page of this module from CPAN
  45.     my $module_url = $cpan_url . $href;
  46.     print "get module_page ...\nurl=$module_url\n";
  47.     $mech->get($module_url);
  48.     my $module_page_content = $mech->content();
  49.     undef $tree;
  50.     $tree = HTML::TreeBuilder->new;
  51.     $success = $tree->parse($module_page_content);
  52.     $success = $tree->eof();
  53.     die "parse module_page_content failed: $!\n" unless $success;

  54.     # find the download url for this module
  55.     my $ps = $tree->query("p[style]");
  56.     for my $p (@$ps) {
  57.         if ($p->as_trimmed_text =~ m/Download:/) {
  58.             my $href = $p->query('a[href]')->attr('href')->[0];
  59.             print "Path = " . $cpan_url . $href . "\n";
  60.             return $cpan_url . $href;
  61.         }
  62.     }
  63.     return undef; # fail if reach here
  64. }

  65. sub install {
  66.     my $module = shift;
  67.     my $suffix = ".tar.gz";

  68.     my $cur_dir = getcwd;
  69.     chdir($tmp_dir);
  70.     print "cur_dir: $cur_dir, chidr to: " . getcwd . "\n";

  71.     # judge if file already exists.
  72.     # for example, file A-B.tar.gz for module A::B
  73.     my @files = grep {-f $_} <*>;
  74.     my $dir = $module;
  75.     $dir =~ s/::/-/g;
  76.     @files = grep /^$dir-(\d.)+/, @files;
  77.     print "files=@files\n";

  78.     # if module.tar.gz does not exists, we wget it from CPAN
  79.     # else use it directly
  80.     unless (@files) {
  81.         my $url = &get_url_from_cpan($module);
  82.         $dir = fileparse($url, $suffix);
  83.         system("wget $url 1>/dev/null 2>&1");
  84.     }
  85.     else {
  86.         $dir = fileparse($files[0], $suffix);
  87.     }

  88.     # unpack the module.tar.gz file
  89.     # and chdir to the related dir
  90.     print "dir = $dir\n";
  91.     system("gunzip < $dir$suffix|tar -xf -");
  92.     chdir($dir);

  93.     # start to install this module
  94.     # 1. perl5 Makefile.PL prefix=$prefix
  95.     # 2. make
  96.     # 3. make install
  97.     # If there is dependency, we should install them first
  98.     # until all dependency are installed.
  99.     my $dependency = 1;
  100.     while ($dependency) {
  101.         my $mf_result = `perl5 Makefile.PL prefix=$prefix 2>&1`;
  102.         if ($mf_result =~ m/Warning: prerequisite (\S*) .* not found/) {
  103.             my ($new_module) = $1 ;
  104.             $new_module =~ s/-(\d.)+$//;
  105.             $new_module =~ s/-/::/g;
  106.             print ">" x 30 . "\n";
  107.             print "$new_module shoulde be installed first\n";
  108.             system("~/bin/cpan_install.pl",  $new_module);
  109.         }
  110.         else {
  111.             $dependency = 0;
  112.         }
  113.     }
  114.     system("make && make install");

  115.     chdir($cur_dir);
  116. }
复制代码

作者: hp_truth   发布时间: 2010-09-10

呵呵··不错~~

作者: wfnh   发布时间: 2010-09-10

回复 wfnh


    谢谢, 就是觉得HTML:uery挺好用的,所以拿来当作练习了。 应该还有别的方法可以下载的。

作者: hp_truth   发布时间: 2010-09-10

赞,我们内部网络也是不能CPAN,正好试试这个!

作者: liyangole   发布时间: 2010-09-10