・ Web系SE募集 (技術開発部開発系エンジニア・Java/Tomcat 420万円~750万円)
   ・ 社内SE募集 (業務系システムの開発・社内イントラ)

perlの最近のブログ記事

POEIKC     http://search.cpan.org/~suzuki/POEIKC-0.04/


2年ほど前のあるWebのシステムで、アクセスの度にリアルタイム処理を行うものを作っておりました。
それは、

HTTPクライアントや、
さまざまな処理を行うワーカー、
集計やログ出力など、
数十台のサーバー上で処理を分担し、
各サーバー間やプロセス間でデータのやりとりをしながら行いました。

それぞれの処理を行うプログラムは
デーモンの様に常駐し、
サーバーの様に処理を受け、
クライアントの様に処理を依頼したりし、
複数のホストにタスクを分担して各ホストやプロセス間でタスクの受け渡しながら、
作業をし続けるプログラムを
用途毎に、幾つも作っていました。

そこで、それらの共通的な要素をいくつもつくる事を考えると楽をしたくなり、
フレームワーク化したものがほしいと考えました。

・どういう工夫をしたのか

1.デーモンとのやりとりを簡単にできるようにクライアントを用意しました。これにより別途クライアントを用意する必要がなくなり、サーバーへの処理依頼を付属のクライアントで行える様になりました。

2.バックグラウンドだけではなく、フォアグラウンドでも動くようにした。これにより標準出力や標準エラーなどを拾いたい時に利用できる。

3.ネットワーク通信・プロセス間通信を行うためPOEを使用しました。これにより、複数のタスクを同時に行う事ができ、リクエストに対するレスポンス待ちといったロスを無くす事ができました。

4.プラグイン的に利用出来るようにしました。これにより、再利用可能なモジュール作りが可能。
    ※今のところ次の2つのプラグインがございます。
POEIKC::Plugin::GlobalQueue ・・・ MessageQueueのようなもの
POEIKC::Plugin::IRC ・・・IRCサーバーへ中継を行うIRCクライアント

5.デーモン(サーバー)間でP2P出来るようにしました。これにより処理毎にプロセスを分け分散処理ができ、負荷分散も可能となった。(同じホスト内でも複数起動可能です)

6.クライアントからデーモンにモジュールをロードできるようにした。これによりリモートでデーモンの設定変更など操作する事が可能。

7.このシステムのベースはPOE::Component::IKCを使用しているのでPOE::Component::IKC:: ClientLite を使う事で、バッチ処理やApacheのプロセスとの通信も可能。

 

前回に引き続き IRCネタです。
IRCサーバーを作った時と同じぐらいの時期に、
をつくりました。
これを作ったきっかけは、SVNでコミット時にメールを送るのに、commit-email.pl を使ってましたが、
こまめにコミットすると、メールに埋もれてしまう~。
という事で、trunk にマージした時のみメールで送る様にし、それ以外は IRCに流そうと思ったわけです。
元ネタは、coderepos のcodereposbot で、codereposbot は コミット時にログを流していたので同じ事を考えました。
で、
commit-email.pl を trunk にコミットした時だけ IRCに情報を流すように少々手を加えます。
その時、バッチ(commit-email.pl)から IRC に手軽に流したいな~。でも。コミットの時だけ IRCに
IRCbotが join して~とかなると、それはそれでわずらわしいしー。とかとか考え、IRCにメッセージを流す中継を行うIRCbotのデーモンを立てるのがいいと思い、手軽にIRCbotを作れるPOEIKC::Plugin::IRC を作ったわけです。
(PoCo::IKCのおかげでデーモンと気軽に会話できるのがいいですね)

POEIKC::Plugin::IRC は、POEIKC の Plugin として使います。
使い方は、POEIKCPOEIKC::Plugin::IRC をインストールしたら、

poeikcd start -M=POEIKC::Plugin::IRC -a=irc_bot -p 6677 -s

として、起動し、svn でメール送信するスクリプト(commit-email.pl)に、

use POE::Component::IKC::ClientLite;

my %param = (
        ip              => Sys::Hostname::hostname,
        port    => 6677,
        name    => join('_'=>Sys::Hostname::hostname, ($0 =~ /(\w+)/g), $$),
);
my $ikc = create_ikc_client(%param);
$ikc or warn $POE::Component::IKC::ClientLite::error;

my @param = ({
        connect=>{
                Nick=>"svn_bot",
                Username=>"svn_bot",
                Ircname=>"svn_bot",
                Port=>"6667",
                flood=>1,
        },
        channel=>"#svn_commit"
});
my $message_respond = 'IKC_IRC/message_respond';
$ikc->post_respond( $message_respond => [@param, $mail_subject]);
$ikc->post_respond( $message_respond => [@param, $mail_body]);
とします。

必要に応じて、trunk にコミットした時だけというロジックを追加したりすれば完成です。

POE::Component::Server::IRC を使用したIRCサーバーです。
POE::Component::Server::IRC は、現時点で最新の VERSION 1.38 を使用します。
 

POCo::Server::IRC を使うので実装は簡単です。
しかしこのバージョンには注意が必要ですのでその辺を記載します。

本題の前に、なぜ IRCサーバー立てるの?ってところから。
 
私は、IRCに関して詳しくは無く、IRCコマンドもほとんどわかりませんが、以前の職場でネタ系や情報共有などにIRCを使っていて良かったので
今の職場でも使いたいと思いました。
それで、今の職場にIRCの導入を進めようと思い、以前の職場でIRCサーバーを立ててた daiba先生 に、どうしたらいいか聞いてみたところ、
サーバーは、
で、Bot(URLのタイトルひろってくるやつ)は
と教えていただいたので、そこにあった、ngIRCd: Next Generation IRC Daemon を使うことにしました。
そして、社内への導入を進めていたのですが、浸透せず、もともと社内でのメッセージのやりとりはIPメッセンジャーを使ってたので
それ以外はだれも使いたがりませんでした。
で、結局社内への導入は失敗し、つまんないの~と思ってて、でも、IRCでの情報共有はいいな~やっておきたいな~と思い、
この地域(私は東京から仙台に引っ越した)にIRC系のサーバーないのかな~と考えるようになりました。
で調べたところ、東北地域にはなかったので、自分で立てることにした。
自分でたてなくても、日本国内には、たくさんのIRCホスト(http://tomocha.net/docs/irc/server_link.html)があるし、海外にもfreenode 
とかがあるから、それらを使えばいーじゃなぃ?というのもあるけど、いろいろ思うところもあり、自分とこにたてる事にした。
で、自分とこにたてるのも、最初は ngIRCd を使っていたんだけど、細かな設定が上手くできなく、POE::Component::Server::IRC の存在も知っていたので、
それならIRCサーバーを作ってしまおうと思ったわけです。
作るといっても、POE::Component::Server::IRC を使うので作るというほどでもないですが、いくつか注意点があったので、それをUPしようと思いました。
 
に、ある、IRCホストirc.arbolbell.jp は、PoCo::Server::IRCを使ってます。ここにある日付からもわかるように、IRCサーバーを立てたのは今年3月はじめなので
今回の記事を書くのに時間がかかってしまいました。
 
本題にもどります。
 
まず、
IRC で SSLでの通信を有効にするために openssl-devel をインストールしときます。
$ sudo yum install openssl-devel

そして、CPANモジュールをインストールです。

cpan> install POE::Component::Server::IRC
cpan> install POE::Component::SSLify


SSL対応にしたいので
use POE::Component::SSLify qw( Server_SSLify SSLify_Options Client_SSLify );
します。


1つめの注意点は、PoCo::Server::IRC Ver 1.38のドキュメントに、SSLでの接続の仕方が書いていないけど、SSL接続に対応していて使えるということ。
私はどこに書いてあるか分からず、SSLでの接続は対応していないかと思いました。
しかし、テストコードを見てみると、しっかりとSSL接続のテストが書いてありました。

POE::Component::Server::IRC でのSSL接続は、
    $heap->{ircd}->add_listener( port => $port_ssl, usessl => 1 );
の様に、add_listenerで、ポートを割り当てる際に usesslフラグを立てることで可能ですが、ドキュメントには書かれていなかったのです。

※add_listenerに関する記述:
add_listener

Takes a number of arguments. Adds a new listener.

        'port', the TCP port to listen on. Default is a random port;
        'auth', enable or disable auth sub-system for this listener. Default enabled;
        'bindaddr', specify a local address to bind the listener to;
        'listenqueue', change the SocketFactory's ListenQueue;

A listener is required to accept connections from clients.



もうひとつ注意が必要なのは、IRCコマンド /info で表示する情報です。
Ver 1.38 では、ソースに記述ミスがあり、いくら設定してもデフォルトの表示しかされません。

その箇所を 修正して diff したのが次のです。

$ diff -u /usr/local/lib/perl5/site_perl/5.10.0/POE/Component/Server/IRC.pm ~/lib/perl/POE/Component/Server/IRC.pm
--- /usr/local/lib/perl5/site_perl/5.10.0/POE/Component/Server/IRC.pm   2009-01-27 22:20:14.000000000 +0900
+++ ~/lib/perl/POE/Component/Server/IRC.pm        2009-03-04 10:21:27.000000000 +0900
@@ -4668,7 +4668,7 @@
     $self->{config}->{ADMIN}->[1] = 'Some Institution';
     $self->{config}->{ADMIN}->[2] = 'someone@somewhere';
   }
-  if ( ( not defined ( $self->{config}->{INFO} ) ) or ( ref $self->{config}->{INFO} eq 'ARRAY' ) or ( scalar ( @{ $self->{config}->{INFO} } ) >= 1 ) ) {
+  if ( ( not defined ( $self->{config}->{INFO} ) ) or ( ref $self->{config}->{INFO} ne 'ARRAY' ) or ( scalar ( @{ $self->{config}->{INFO} } ) == 0 ) ) {
     $self->{config}->{INFO}->[0] = '# POE::Component::Server::IRC';
     $self->{config}->{INFO}->[1] = '#';
     $self->{config}->{INFO}->[2] = '# Author: Chris "BinGOs" Williams';
 
 
で使っている IRCサーバーのソースと設定ファイル

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;
use YAML;
use Class::Inspector;
use POE qw(Component::Server::IRC);
use POE::Component::SSLify qw( Server_SSLify SSLify_Options Client_SSLify );


# 設定ファイル読み込み
my $yaml = YAML::LoadFile('irc.yaml');

# 通常運用時と、テスト起動時のポート
my ($switch) = @ARGV || ("");
my ($port_nossl, $port_ssl) = $switch =~ /test/i ? @{$yaml->{test_port}} : @{$yaml->{port}} ;

my $pocosi = POE::Component::Server::IRC->spawn( 
	config 			=> $yaml->{config},
	antiflood 		=> $switch =~ /test/i ? 0 : 1,
	debug 			=> $yaml->{debug},
	sslify_options 	=> $yaml->{sslify_options},
);

POE::Session->create(
	package_states => [ main =>  Class::Inspector->methods(__PACKAGE__) ],
    heap => { ircd => $pocosi },
);

$poe_kernel->run();
exit 0;

my @operator;
sub _start {
	my ($kernel,$heap) = @_[KERNEL,HEAP];
	$kernel->sig( HUP  => '_stop' );
	$kernel->sig( INT  => '_stop' );
	$kernel->sig( TERM => '_stop' );
	$kernel->sig( KILL => '_stop' );
	$heap->{ircd}->yield( 'register' );
	$heap->{ircd}->add_auth( mask => '*@*' );
	$heap->{ircd}->add_listener( port => $port_nossl );
	$heap->{ircd}->add_listener( port => $port_ssl, usessl => 1 );
	# オペレーター
	for( @{$yaml->{operator}} ){
		push @operator, $_->{username};
		$heap->{ircd}->add_operator( $_ );
	}
	# 起動時にチャンネルを作成するためのユーザーを作成
	$heap->{ircd}->yield(add_spoofed_nick=>{nick=>'ircd_bot', ircname => 'The IRC Serv Bot'});
	# 起動時に作成しておくチャンネル
	while ( my ($channel, $topic) = each %{$yaml->{channel_list}} ) {
		$heap->{ircd}->yield(daemon_cmd_join =>'ircd_bot',$channel);
		$heap->{ircd}->yield(daemon_cmd_topic=>'ircd_bot',$channel, $topic);
	}
	undef;
}


sub ircd_daemon_join {
    my $kernel  = $_[KERNEL];
    my $heap    = $_[HEAP];
    my $session = $_[SESSION];
	my ($full_user, $channel) = @_[ARG0, ARG1];
	# オペレーター
	for my $username( @operator ){
		if($full_user =~ /^$username!~$username/ and $heap->{ircd}->state_user_is_operator($username)){
			$heap->{ircd}->yield(daemon_cmd_mode=>'ircd_bot',$channel,'+o',$username);
			last;
		}
	}
}

sub _stop {
    my $heap    = $_[HEAP];
	$heap->{ircd}->yield( 'shutdown' );
	delete $heap->{ircd};
}

sub _default {
 my ( $event, $args ) = @_[ ARG0 .. $#_ ];
 print STDOUT "$event: ";
 foreach (@$args) {
 SWITCH: {
          if ( ref($_) eq 'ARRAY' ) {
              print STDOUT "[", join ( ", ", @$_ ), "] ";
              last SWITCH;
          }
          if ( ref($_) eq 'HASH' ) {
              print STDOUT "{", join ( ", ", %$_ ), "} ";
              last SWITCH;
          }
          print STDOUT "'$_' ";
      }
  }
  print STDOUT "\n";
  return 0;    # Don't handle signals.
}


 

$ cat irc.yaml
---
channel_list:
  '#lounge': ラウンジ. http://arbolbell.jp/irc
  '#test': テスト用. http://arbolbell.jp/irc
config:
  admin:
    - irc.arbolbell.jp
    - http://arbolbell.jp/irc
    - suzu@mail.*****.jp
  info:
    - '******************'
    - http://arbolbell.jp/irc
    - '******************'
  motd:
    - ''
    - ''
    - ''
    - ''
    - '    ----------------------------------------------------------------------'
    - '    The character code of this host is UTF-8.'
    - '    ----------------------------------------------------------------------'
    - ''
    - '    ようこそ irc.arbolbell.jp へ'
    - ''
    - '    ※実験的に立ち上げているサーバのため、予告無く再起動、停止等が行われる'
    - '      場合があります。あしからず御了承ください。'
    - '    ※全ては無保証で一切責任を負いませんので自己責任でご利用下さい。'
    - ''
    - '    このIRCサーバーはSSLに対応しています。'
    - '    SSL対応のクライアントをご利用の場合、SSLで接続可能です。'
    - ''
    - '    SSL接続  ポート番号:6668 '
    - '    非SSL接続ポート番号:6667'
    - ''
    - '    このIRCホストに関しては、http://arbolbell.jp/irc を参照してください。'
    - ''
    - '    ★次のチャンネルは、サーバー起動時に作られます。'
    - '      #lounge  ・・・・ラウンジです。'
    - '      #test    ・・・・テスト用です。'
    - ''
    - '    ★チャンネル作成のガイドライン '
    - '     ・チャンネル名は、わかりやすい名前を付けてください。 '
    - '     ・topic も、わかりやすくおねがいします。'
    - '     ・topic は必ず設定してください。'
    - ''
    - '    ----------------------------------------------------------------------'
  network: arbolbell.jp
  nicklen: 15
  serverdesc: http://arbolbell.jp/irc
  servername: irc.arbolbell.jp
  version: irc.arbolbell.jp 0.01
debug: 1
operator:
  - ipmask: '*'
    password: mypass1
    username: suzuk1
  - ipmask: '*'
    password: mypass2
    username: suzuk2
port:
  - 6667
  - 6668
sslify_options:
  - ./server-key.pem
  - ./server-cert.pem
test_port:
  - 16667
  - 16668

 

インストールした mod_perl2 の動作確認を Apache::Test で行う。

※mod_perl2のインストールは次の手順で行う。

※ Apache::Test は、mod_perl2をインストールする前に、install Bundle::Apache2 した時にインストールされます。


ファイル構成
$ tree ModPerlTest-0.01
ModPerlTest-0.01
|-- Changes
|-- MANIFEST
|-- META.yml
|-- Makefile.PL
|-- README
|-- lib
|   |-- ModPerlTest
|   |   |-- ResponseCleanup.pm
|   |   `-- ResponseHandler.pm
|   `-- ModPerlTest.pm
`-- t
    |-- 00_compile.t
    |-- 01_resp1.t
    |-- 01_resp2.t
    |-- 02_respClean.t
    |-- TEST
    |-- TEST.PL
    |-- conf
    |   `-- extra.conf.in
    `-- response
        `-- ModPerlTest
            `-- ResponseTestHandler.pm

6 directories, 16 files

設定ファイル extra.conf.in

LoadModule apreq_module    /usr/local/apache2/modules/mod_apreq2.so

<location responsehandler="">
        SetHandler perl-script
        PerlResponseHandler ModPerlTest::ResponseHandler
</location> 

<location responsecleanup="">
        SetHandler perl-script
        PerlResponseHandler ModPerlTest::ResponseCleanup
</location>  

ModPerlTest::ResponseHandler

パラメータを受けて返す レスポンスハンドラ

package ModPerlTest::ResponseHandler;

use Apache2::RequestUtil ();
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Const -compile => ':common';
use Apache2::Request;

use strict;
use 5.008_001;
our $VERSION = '0.01';

sub handler {
        my $r = shift;
        my $query  = Apache2::Request->new($r);
        my $param = $query->param if( $query->param );
        $param ||= {};
        my $input = $param->{input} || '';
        $r->content_type('text/html');
        $r->puts(__PACKAGE__ ."\t". $input);
        return Apache2::Const::OK;
}

1;
__END__

ModPerlTest::ResponseHandler にリクエストを送るためのテストコード

01_resp1.t

use strict;
use Apache::Test qw(:withtestmore);
use Apache::TestUtil;
use Apache::TestRequest 'GET_BODY';
use Test::More ( tests => 1 );
use URI;

my $input = 'ABC';
my $url = URI->new("/responseHandler?input=$input");
my $data = GET_BODY $url;
is ($data, "ModPerlTest::ResponseHandler\t$input");

1;

01_resp2.t

use strict;
use Apache::Test qw(:withtestmore);
use Apache::TestUtil;
use Apache::TestRequest 'GET_BODY';
use Test::More ( tests => 1 );
use URI;

my $url = URI->new("/responseHandler?input=$$");
my $data = GET_BODY $url;
is ($data, "ModPerlTest::ResponseHandler\t$$");

1;

cleanup_register を使用したレスポンスハンドラ

ModPerlTest::ResponseCleanup

package ModPerlTest::ResponseCleanup;

use Apache2::RequestUtil ();
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Const -compile => ':common';

use strict;
use 5.008_001;
our $VERSION = '0.01';

sub handler {
        my $r = shift;

        $r->content_type('text/html');
        $r->puts($$);
        $r->pool->cleanup_register(\&cleanup, time);
        return Apache2::Const::OK;
}

use Fcntl qw(:DEFAULT :flock);

sub cleanup{
        my $t = shift;
        my $file = "/tmp/mod_perl_test.$$.txt";
        sysopen(FH, $file, O_WRONLY | O_CREAT) or die "can't open $file: $!";
        print FH join("\t"=> $t, time, $$);
        close FH;
        return Apache2::Const::OK;
}

1;
__END__

ModPerlTest::ResponseCleanup にリクエストを送るためのテストコード

02_respClean.t

use strict;
use Apache::Test qw(:withtestmore);
use Apache::TestUtil;
use Apache::TestRequest 'GET_BODY';
use Test::More ( tests => 1 );
use URI;

my $url = URI->new("/responseCleanup");
my $pid = GET_BODY $url;
my $count=0;
my $fpid;
my ($t1, $t2);
use Fcntl qw(:DEFAULT :flock);
my $file = "/tmp/mod_perl_test.$pid.txt";
while(1){
        last if $count > 10;
        $count++;
        $fpid ||= '';
        sysopen(FH, $file, O_RDONLY) or  next;
        ($t1, $t2, $fpid) = split /\t/,(shift @{[]});
	close FH;
	last;
}
is($pid , $fpid, "($pid , $fpid)");
unlink $file;

1;

レスポンスハンドラ の中に書くテストコード

ModPerlTest::ResponseTestHandler

package ModPerlTest::ResponseTestHandler;

use Apache::Test;
use Apache2::RequestUtil ();
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Const -compile => ':common';
use Apache2::Request;

use strict;
use 5.008_001;
our $VERSION = '0.01';

sub handler {
        my $r = shift;
        plan $r, tests => 1;
        ok ref $r;
        return Apache2::Const::OK;
}

1;

テスト結果

$ perl Makefile.PL
[   info] generating script t/TEST
Checking if your kit is complete...
Looks good
Warning: prerequisite UNIVERSAL::require 0 not found.
Writing Makefile for ModPerlTest


$ make test
cp lib/ModPerlTest/ResponseHandler.pm blib/lib/ModPerlTest/ResponseHandler.pm
cp lib/ModPerlTest/ResponseCleanup.pm blib/lib/ModPerlTest/ResponseCleanup.pm
cp lib/ModPerlTest.pm blib/lib/ModPerlTest.pm
/usr/local/bin/perl -Iblib/arch -Iblib/lib \
        t/TEST  -clean
setting ulimit to allow core files
ulimit -c unlimited; /usr/local/bin/perl /home/suzu/work/ModPerlTest-0.01/t/TEST -clean
APACHE_TEST_GROUP= APACHE_TEST_HTTPD= APACHE_TEST_PORT= APACHE_TEST_USER= APACHE_TEST_APXS= \
        /usr/local/bin/perl -Iblib/arch -Iblib/lib \
        t/TEST  -bugreport -verbose=0
setting ulimit to allow core files
ulimit -c unlimited; /usr/local/bin/perl /home/suzu/work/ModPerlTest-0.01/t/TEST -bugreport -verbose=0
/usr/local/apache2/bin/httpd  -d /home/suzu/work/ModPerlTest-0.01/t -f /home/suzu/work/ModPerlTest-0.01/t/conf/httpd.conf -D APACHE2
using Apache/2.2.9 (prefork MPM)
waiting 60 seconds for server to start: 00:00[Sat Oct 04 00:43:51 2008] [warn] module apreq_module is already loaded, skipping
waiting 60 seconds for server to start: ok (waited 1 secs)
server localhost.localdomain:8529 started
t/00_compile.........................ok
t/01_resp1...........................ok
t/01_resp2...........................ok
t/02_respClean.......................ok
t/modperltest/responsetesthandler....ok
All tests successful.
Files=5, Tests=6,  4 wallclock secs ( 0.09 usr  0.01 sys +  2.52 cusr  0.95 csys =  3.57 CPU)
Result: PASS
server localhost.localdomain:8529 shutdown
$
$ cat ./t/logs/access_log
127.0.0.1 - - [04/Oct/2008:00:43:53 +0900] "GET /index.html HTTP/1.0" 200 795
127.0.0.1 - - [04/Oct/2008:00:43:54 +0900] "GET /responseHandler?input=ABC HTTP/1.0" 200 32
127.0.0.1 - - [04/Oct/2008:00:43:55 +0900] "GET /responseHandler?input=3790 HTTP/1.0" 200 33
127.0.0.1 - - [04/Oct/2008:00:43:55 +0900] "GET /responseCleanup HTTP/1.0" 200 4
127.0.0.1 - - [04/Oct/2008:00:43:56 +0900] "GET /ModPerlTest__ResponseTestHandler HTTP/1.0" 200 217
$ cat ./t/logs/error_log
[Sat Oct 04 00:43:51 2008] [info] Init: Seeding PRNG with 0 bytes of entropy
[Sat Oct 04 00:43:51 2008] [info] Init: Generating temporary RSA private keys (512/1024 bits)
[Sat Oct 04 00:43:51 2008] [info] Init: Generating temporary DH parameters (512/1024 bits)
[Sat Oct 04 00:43:51 2008] [warn] Init: Session Cache is not configured [hint: SSLSessionCache]
[Sat Oct 04 00:43:51 2008] [info] Init: Initializing (virtual) servers for SSL
[Sat Oct 04 00:43:51 2008] [info] mod_ssl/2.2.9 compiled against Server: Apache/2.2.9, Library: OpenSSL/0.9.8g
[Sat Oct 04 00:43:51 2008] [warn] module apreq_module is already loaded, skipping
[Sat Oct 04 00:43:51 2008] [info] Init: Seeding PRNG with 0 bytes of entropy
[Sat Oct 04 00:43:51 2008] [info] Init: Generating temporary RSA private keys (512/1024 bits)
[Sat Oct 04 00:43:52 2008] [info] Init: Generating temporary DH parameters (512/1024 bits)
[Sat Oct 04 00:43:52 2008] [info] Init: Initializing (virtual) servers for SSL
[Sat Oct 04 00:43:52 2008] [info] mod_ssl/2.2.9 compiled against Server: Apache/2.2.9, Library: OpenSSL/0.9.8g
[Sat Oct 04 00:43:52 2008] [notice] Apache/2.2.9 (Unix) mod_ssl/2.2.9 OpenSSL/0.9.8g mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0 configured -- resuming normal operations
[Sat Oct 04 00:43:52 2008] [info] Server built: Sep 20 2008 19:27:27
[Sat Oct 04 00:43:52 2008] [debug] prefork.c(1001): AcceptMutex: sysvsem (default: sysvsem)
[Sat Oct 04 00:43:57 2008] [info] removed PID file /home/suzu/work/ModPerlTest-0.01/t/logs/httpd.pid (pid=3778)
[Sat Oct 04 00:43:57 2008] [notice] caught SIGTERM, shutting down

今回使用したファイル。

ModPerlTest-0.01.tar.gz


root権限ではなく、ユーザー権限で、make test したい場合があります。
その時は、CPANシェルをユーザー権限で実行します。
そのための設定です。

mod_perlをインストールする時は、root権限での make test がうまくいきません。そういう時はユーザー権限でインストールします。

初めてcpanシェルを起動した時のセットアップ。

$ sudo su -
Password:
[root@localhost ~]# cpan


CPAN is the world-wide archive of perl resources. It consists of about
300 sites that all replicate the same contents around the globe. Many
countries have at least one CPAN site already. The resources found on
CPAN are easily accessible with the CPAN.pm module. If you want to use
CPAN.pm, lots of things have to be configured. Fortunately, most of
them can be determined automatically. If you prefer the automatic
configuration, answer 'yes' below.

If you prefer to enter a dialog instead, you can answer 'no' to this
question and I'll let you configure in small steps one thing after the
other. (Note: you can revisit this dialog anytime later by typing 'o
conf init' at the cpan prompt.)
Would you like me to configure as much as possible automatically? [yes]

(省略)

Autoconfigured everything but 'urllist'.
Please call 'o conf init urllist' to configure your CPAN server(s) now!

commit: wrote '/usr/local/lib/perl5/5.10.0/CPAN/Config.pm'
Terminal does not support AddHistory.

cpan shell -- CPAN exploration and modules installation (v1.9205)
ReadLine support available (maybe install Bundle::CPAN or Bundle::CPANxxl?)

cpan[1]>

初めてCPANシェルを起動した時は、「Would you like me to configure as much as possible automatically? [yes]」と聞かれるので、デフォルト(Yes)のままEnterを押す。

再設定をしたい場合は、

cpan[2]> o conf init

とする事で、設定し直す事ができる。その時、「Would you like me to configure as much as possible automatically? [yes]」では no にするとよい


設定内容を確認する。

cpan[1]> o conf
$CPAN::Config options from '/usr/local/lib/perl5/5.10.0/CPAN/Config.pm':
    commit             [Commit changes to disk]
    defaults           [Reload defaults from disk]
    help               [Short help about 'o conf' usage]
    init               [Interactive setting of all options]

    applypatch         []
    auto_commit        [0]
    build_cache        [100]
    build_dir          [/root/.cpan/build]
    build_dir_reuse    [1]
    build_requires_install_policy [ask/yes]
    bzip2              [/usr/bin/bzip2]
    cache_metadata     [1]
    check_sigs         [0]
    colorize_debug     undef
    colorize_output    undef
    colorize_print     undef
    colorize_warn      undef
    commandnumber_in_prompt [1]
    commands_quote     undef
    cpan_home          [/root/.cpan]
    curl               [/usr/bin/curl]
    dontload_hash      undef
    dontload_list      undef
    ftp                []
    ftp_passive        [1]
    ftp_proxy          []
    getcwd             [cwd]
    gpg                []
    gzip               [/bin/gzip]
    histfile           [/root/.cpan/histfile]
    histsize           [100]
    http_proxy         []
    inactivity_timeout [0]
    index_expire       [1]
    inhibit_startup_message [0]
    keep_source_where  [/root/.cpan/sources]
    load_module_verbosity [v]
    lynx               []
    make               [/usr/bin/make]
    make_arg           []
    make_install_arg   []
    make_install_make_command [/usr/bin/make]
    makepl_arg         []
    mbuild_arg         []
    mbuild_install_arg []
    mbuild_install_build_command [./Build]
    mbuildpl_arg       []
    ncftp              []
    ncftpget           []
    no_proxy           []
    pager              [/usr/bin/less]
    password           undef
    patch              [/usr/bin/patch]
    prefer_installer   [MB]
    prefs_dir          [/root/.cpan/prefs]
    prerequisites_policy [ask]
    proxy_pass         undef
    proxy_user         undef
    randomize_urllist  undef
    scan_cache         [atstart]
    shell              [/bin/bash]
    show_unparsable_versions [0]
    show_upload_date   [0]
    show_zero_versions [0]
    tar                [/bin/tar]
    tar_verbosity      [v]
    term_is_latin      [1]
    term_ornaments     [1]
    test_report        [0]
    unzip              []
    urllist
    use_sqlite         [0]
    username           undef
    wait_list          undef
    wget               [/usr/bin/wget]
    yaml_load_code     [0]
    yaml_module        [YAML]


cpan[2]> 

CPAN シェルで使えるコマンドを確認する。

cpan[2]> help

Display Information                                                (ver 1.9205)
 command  argument          description
 a,b,d,m  WORD or /REGEXP/  about authors, bundles, distributions, modules
 i        WORD or /REGEXP/  about any of the above
 ls       AUTHOR or GLOB    about files in the author's directory
    (with WORD being a module, bundle or author name or a distribution
    name of the form AUTHOR/DISTRIBUTION)

Download, Test, Make, Install...
 get      download                     clean    make clean
 make     make (implies get)           look     open subshell in dist directory
 test     make test (implies make)     readme   display these README files
 install  make install (implies test)  perldoc  display POD documentation

Upgrade
 r        WORDs or /REGEXP/ or NONE    report updates for some/matching/all modules
 upgrade  WORDs or /REGEXP/ or NONE    upgrade some/matching/all modules

Pragmas
 force  CMD    try hard to do command  fforce CMD    try harder
 notest CMD    skip testing

Other
 h,?           display this menu       ! perl-code   eval a perl command
 o conf [opt]  set and query options   q             quit the cpan shell
 reload cpan   load CPAN.pm again      reload index  load newer indices
 autobundle    Snapshot                recent        latest CPAN uploads

urllist を設定する。

cpan[3]> o conf init urllist
You have no /root/.cpan/sources/MIRRORED.BY
  I'm trying to fetch one

I would like to connect to one of the following sites to get 'MIRRORED.BY':

 http://www.perl.org/CPAN/
 ftp://ftp.perl.org/pub/CPAN/

Is it OK to try to connect to the Internet? [yes]
  LWP not available

Trying with "/usr/bin/curl -L -f -s -S --netrc-optional" to get
    http://www.perl.org/CPAN/MIRRORED.BY


Now we need to know where your favorite CPAN sites are located. Push
a few sites onto the array (just in case the first on the array won't
work). If you are mirroring CPAN to your local workstation, specify a
file: URL.

First, pick a nearby continent and country by typing in the number(s)
in front of the item(s) you want to select. You can pick several of
each, separated by spaces. Then, you will be presented with a list of
URLs of CPAN mirrors in the countries you selected, along with
previously selected URLs. Select some of those URLs, or just keep the
old list. Finally, you will be prompted for any extra URLs -- file:,
ftp:, or http: -- that host a CPAN mirror.

(1) Africa
(2) Asia
(3) Central America
(4) Europe
(5) North America
(6) Oceania
(7) South America
Select your continent (or several nearby continents) [] 2

(1) China
(2) Hong Kong
(3) Indonesia
(4) Israel
(5) Japan
(6) Korea
(7) Pakistan
(8) Philippines
(9) Republic of Korea
(10) Saudi Arabia
(11) Singapore
(12) Taiwan
(13) Thailand
(14) Turkey
Select your country (or several nearby countries) [] 5

(1) ftp://ftp.dti.ad.jp/pub/lang/CPAN/
(2) ftp://ftp.jaist.ac.jp/pub/CPAN/
(3) ftp://ftp.kddilabs.jp/CPAN/
(4) ftp://ftp.nara.wide.ad.jp/pub/CPAN/
(5) ftp://ftp.riken.jp/lang/CPAN/
(6) ftp://ftp.ring.gr.jp/pub/lang/perl/CPAN/
(7) ftp://ftp.u-aizu.ac.jp/pub/CPAN
(8) ftp://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/
Select as many URLs as you like (by number),
put them on one line, separated by blanks, hyphenated ranges allowed
 e.g. '1 4 5' or '7 1-4 8' [] 2 3

Enter another URL or RETURN to quit: []
New set of picks:
  ftp://ftp.jaist.ac.jp/pub/CPAN/
  ftp://ftp.kddilabs.jp/CPAN/


Please remember to call 'o conf commit' to make the config permanent!


cpan[4]> o conf
$CPAN::Config options from '/usr/local/lib/perl5/5.10.0/CPAN/Config.pm':
(省略)
    urllist
        0 [ftp://ftp.jaist.ac.jp/pub/CPAN/]
        1 [ftp://ftp.kddilabs.jp/CPAN/]

install Bundle::CPAN

cpan[5]> install Bundle::CPAN
CPAN: Storable loaded ok (v2.18)

Trying with "/usr/bin/curl -L -f -s -S --netrc-optional" to get
    ftp://ftp.jaist.ac.jp/pub/CPAN/authors/01mailrc.txt.gz
CPAN: Compress::Zlib loaded ok (v2.008)
Going to read /root/.cpan/sources/authors/01mailrc.txt.gz
............................................................................DONE

Trying with "/usr/bin/curl -L -f -s -S --netrc-optional" to get
    ftp://ftp.jaist.ac.jp/pub/CPAN/modules/02packages.details.txt.gz
Going to read /root/.cpan/sources/modules/02packages.details.txt.gz
  Database was generated on Sun, 21 Sep 2008 08:03:21 GMT
  HTTP::Date not available
.....

途中で

Enter arithmetic or Perl expression: exit
と聞かれる。そのまま Enter を押す。
Continue installing YAML.pm? [y]

これも、そのまま Enter 。


インストール後の最後の表示内容。

CPAN: Term::ReadLine::Perl loaded ok (v1.0302)
.....................
21 subroutines in Term::ReadLine redefined
Exiting subroutine via last at /usr/local/lib/perl5/5.10.0/CPAN.pm line 1450.

cpan shell -- CPAN exploration and modules installation (v1.9205)
ReadLine support enabled

cpan[6]>

The Perl Directory at Perl.org にアクセスしソースをダウンロードする。

downloads を開き、Stable Release の Perl 5.10.0 (Download) からダウンロードする。

http://www.cpan.org/src/README.html

wget http://www.cpan.org/authors/id/R/RG/RGARCIA/perl-5.10.0.tar.gz
tar xzvf perl-5.10.0.tar.gz
cd perl-5.10.0

#Configureのオプションを確認する。
./Configure --help

このアーカイブについて

このページには、過去に書かれたブログ記事のうちperlカテゴリに属しているものが含まれています。

前のカテゴリはMySQLです。

次のカテゴリはPythonです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。