Perlモジュールの検索

インターネットサーバーにインストールされているPerlモジュールの一覧を表示する Perl/CGIプログラム を作成してみましょう。

Perl/CGIプログラミング をする上で、設置先のインターネットサーバーにインストールされているPerlモジュール名を知っておくのはとても大切です。

なぜなら、各種モジュールのインストール状況により、Perl/CGIプログラムでできることがかわってくるからです。

もしあなたが専用サーバーを使っているのであれば、必要に応じて自由に各種Perlモジュールをインストールすることができます。

しかしほとんどの人の場合、共用サーバーを使っていると思います。

共用サーバーの場合、こちら側でインストールできるPerlモジュールには限りがあります。

もし共用サーバーでPerlモジュールをインストールしたい場合には、 CPAN で使いたいPerlモジュールのファイルを直接ダウンロードします。

そしてPerl/CGIプログラムの頭で、「use lib モジュールまでの 絶対パスまたは相対パス ;」とコーディングします。

これである程度のPerlモジュールは使えるようになります。

CGIモジュール はこのパターンで使えます。

もちろん、このパターンで使えないPerlモジュールもあります。

その場合は残念ながらあきらめるしかありません。

このようなことがないよう、現在サーバーにインストールされているPerlモジュール名を知っておくことはとても大切なことなのです。

しかし、レンタルサーバー会社のホームページによっては、インストールされている各種Perlモジュールの情報を掲載してないところもあります。

それでは困るので、現在インターネットサーバーにインストールされているPerlモジュール名を取得して、一覧表示するPerl/CGIプログラムを作成しておきましょう。

以前、Perl/CGIプログラムから サーバーOS Perlパス Sendmailパス などの情報を取得しましたね。

今回はその続きみたいなものです。

  1. Perl/CGIプログラム作成
  2. Perl/CGIプログラム解説

Perl/CGIプログラム作成

インターネットサーバーにインストールされている各種Perlモジュールの情報を取得して、一覧表示するPerl/CGIプログラムを作成してみましょう。

#!/usr/bin/perl

use strict;

my %modules = &GetModules;
my $number = 0;

print "Content-type: text/html\n\n";
foreach my $name (sort keys %modules) {
$number += 1;
print "${number}.\x20${name}<br>\n";
foreach my $path (@{$modules{$name}}) {
print "${path}<br>\n";
}
}
exit;


sub GetModules {
my @include = @INC;
my @delete = ();
my %modules = ();
my $number = 0;

for (my $i=0;$i<=$#INC;$i++) {
if ($INC[$i] eq '.') {next;}
for (my $j=0;$j<=$#INC;$j++) {
if ($INC[$j] eq '.') {next;}
if ($INC[$i] =~ /^${INC[$j]}.+/) {
push @delete, $i;
last;
}
}
}

my $deletelist = &UniqueArray(\@delete);
foreach (sort {$b <=> $a} @{$deletelist}) {
splice (@include, $_, 1);
}

foreach my $path (@include) {
my %findmodules = &FindModules($path);
foreach my $name (keys %findmodules) {
push @{$modules{$name}}, @{$findmodules{$name}};
}
}

return %modules;
}


sub FindModules {
my($path) = @_;
my %modules = ();

opendir (DIRECTORY, $path);
my @files = readdir (DIRECTORY);
closedir (DIRECTORY);

foreach my $file (@files) {
if ($file =~ /^\./) {next;}
if (-d "$path/$file") {
my %submodules = &FindModules("$path/$file");
foreach my $name (keys %submodules) {
push @{$modules{$name}}, @{$submodules{$name}};
}
} else {
if ($file =~ /\.pm$/) {
if (open (FILE, "$path/$file")) {
while (<FILE>) {
if (/^\s*package\s+(\S+)\s*;/){
push @{$modules{$1}}, "$path/$file";
last unless ($file eq 'DB_File.pm');
}
}
close(FILE);
}
}
}
}

return %modules;
}


sub UniqueArray {
my @arrayreference = @_;
my @unique = ();
my %hash = ();

foreach my $arraynumber (@arrayreference) {
foreach my $key (@{$arraynumber}) {
next if ($key eq '');
next if ($hash{$key});
$hash{$key} = 1;
push @unique, $key;
}
}

return \@unique;
}

__END__

このPerl/CGIプログラムを実行すると、だいたいこんな感じに表示されます。

...
71. CGI
/usr/lib/perl5/5.8.8/CGI.pm
72. CGI::Carp
/usr/lib/perl5/5.8.8/CGI/Carp.pm
73. CGI::Cookie
/usr/lib/perl5/5.8.8/CGI/Cookie.pm
74. CGI::Fast
/usr/lib/perl5/5.8.8/CGI/Fast.pm
75. CGI::Pretty
/usr/lib/perl5/5.8.8/CGI/Pretty.pm
76. CGI::Push
/usr/lib/perl5/5.8.8/CGI/Push.pm
77. CGI::Util
/usr/lib/perl5/5.8.8/CGI/Util.pm
...

たくさんのPerlモジュールが表示されるのでご注意ください。

Perl/CGIプログラム解説

それではこのPerl/CGIプログラムについて解説します。

Perl/CGIプログラムが利用できるPerlモジュールの参照パスリストは、特殊変数「@INC」に格納されています。

なので、この特殊変数「@INC」の内容を参照して表示させればある程度は形になります。

しかしそれでは、Perl/CGIプログラムの参照リスト(絶対パスのリスト)が表示されるだけです。

それではPerl/CGIプログラミング入門者や初心者が見てもわけわからないと思うので、Perlモジュール名も一緒に表示できるようにしました。

メイン処理

メイン処理では、 サブルーチン GetModulesで取得したPerlモジュールの名称とパスを ループ を使って表示させています。

メイン処理にかかわらず、このPerl/CGIプログラム内にでてくる ハッシュ配列 「%modules」のデータ構造は以下のようになっています。

ハッシュ配列「%modules」のキーは、Perlモジュール名を使用しています。

そしてハッシュ配列「%modules」の各要素には、Perlモジュールのパスを格納していますが、パスはひとつとは限らないので配列形式にして格納しています。

なので外見はハッシュ配列ですが、各要素の中身は 配列 なので注意する必要があります。

GetModules関数

GetModules関数は、Perlモジュール名とパスのペアを取得します。

まず、Perlモジュールの参照先のリストを格納している特殊変数「@INC」の情報をある程度絞る必要があります。

なぜならこの先の処理を考えると非効率だからです。

削除リスト「@delete」を作成し、 内容の重複している要素はUniqueArray関数 でひとつにまとめます。

そして特殊変数「@INC」のコピーである「@include」の中で、不要な要素(パス)を splice関数 で削除していきます。

このとき、 sort関数を使って要素番号の大きなものから指定 して削除していくことがポイントです。

こうして作成しましたパス群にたいして、ひとつひとつFindModules関数を使ってPerlモジュール情報を取得していきます。

FindModules関数の戻り値のハッシュ配列「%findmodules」は、前述の「%modules」と同じデータ構造をしています。

なので、 foreachループ でひとつずつキーとなっているPerlモジュール名を取り出し、ハッシュ配列「%modules」に対して同名のキーを指定し push関数 を使って取得したパスを追加していきます。

これで、Perlモジュールの名称とパス情報のペアを格納したハッシュ配列「%modules」が完成しました。

あとはreturn関数で値を返してこのサブルーチン終了です。

FindModules関数

FindModules関数は、指定されたパス以降にPerlモジュールがあればその情報を取得するサブルーチンです。

まず、 指定されたパス(フォルダまたはディレクトリ)を開いてその一覧を取得 します。

次に取得しましたファイルやフォルダの一覧からひとつずつ処理していきます。

先頭に「.」がついているものというのは、親の階層があることをあらわす「..」や、「.htaccess」など、Perlモジュールとは関係ないのでnext関数で次に飛ばします。

ファイルテスト演算子「-d」 で、フォルダまたはディレクトリであることがわかった場合には、再びFindModules関数を呼び出しPerlモジュールの情報を取得させます。

ちなみにこのように自分で自分を呼び出すことを、プログラミングの専門用語で再帰呼び出しといいます。

返された値「%submodules」も、前述の「%modules」と同じデータ構造をしているので、また同じようにpush関数を使って代入していきます。

残りは何らかのファイルだった場合です。

Perlモジュールの場合、ファイル名の拡張子は「pm」となっています。

なので if文 パターンマッチ で該当するファイルを探します。

そしてPerlモジュールを見つけたら、その ファイルをopen関数で開いて モジュール名を取得します。

Perlモジュール名は、 関数ライブラリ で学習したように「package 名前;」というフォーマットになっているので 正規表現とパターンマッチ で取り出します。

こうして取得したPerlモジュール名はハッシュ配列「%modules」のキーに、パスは値として順次格納されていくわけです。

<戻る>