You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl-cvs@perl.apache.org by sb...@hyperreal.org on 1998/12/03 21:51:13 UTC
cvs commit: modperl-site/guide/images mod_perl.gif mod_perl2.jpg
sbekman 98/12/03 12:51:12
Added: guide config.html control.html debug.html help.html
index.html intro.html obvious.html performance.html
porting.html scenario.html snippets.html start.html
status.html warnings.html
guide/images mod_perl.gif mod_perl2.jpg
Log:
mod_perl mini guide - Initial release (1.0)
Revision Changes Path
1.1 modperl-site/guide/config.html
Index: config.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: mod_perl Configuration </TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
mod_perl Configuration </H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#configuration">configuration</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="configuration">configuration</A></H1></CENTER>
<P>
<PRE> After installation of the apache with mod_perl you have to change apache's
config files, to make it work.
Add to these files:
httpd.conf (at the bottom):
_________________________________________________________________
# startup.perl loads all functions that we want to use within mod_perl
Perlrequire /path/to/startup.pl
# To reload PerlRequire's, PerlModule's, other use()'d modules and flush
# the Apache::Registry cache, enable with this command:
PerlFreshRestart On
# mod_perl
# mod_perl scripts root location
<Location /perl>
#AllowOverride None
SetHandler perl-script
PerlHandler Apache::Registry
Options ExecCGI
allow from all
PerlSendHeader On
</Location>
#&nbsp;Status location (shows different mod_perl statuses)
<Location /perl-status>
SetHandler perl-script
PerlHandler Apache::Status
order deny,allow
#deny from all
#allow from
</Location>
_________________________________________________________________
Perlrequire startup.pl pulls
up all the modules we want to use with mod_perl and want them to be preloaded.
startup.pl:
_____________________________________________________
use strict;
#modify @INC if needed
use lib qw(/some/other/dir /some/bar/dir);
# make sure we are in a sane environment.
$ENV{GATEWAY_INTERFACE} =~ /^CGI-Perl/ or die &quot;GATEWAY_INTERFACE not Perl!&quot;;
# for things in the &quot;/perl&quot; URL
use Apache::Registry;
#load perl modules of your choice here
#this code is interpreted *once* when the server starts
#use CGI::Switch ();
#use LWP::UserAgent ();
#use DBI ();
# tell me more about warnings
use Carp ();
$SIG{__WARN__} = \&amp;Carp::cluck;
# Load CGI.pm and call its compile() method to precompile its autoloaded methods.
use CGI ();
CGI->compile(':all');
=head1 Perl Sections
</PRE>
<P>
With <Perl></Perl> sections, it is possible to configure your
server entirely in Perl.
<P>
<Perl> sections can contain *any* and as much Perl code as you wish.
These sections are compiled into a special package who's symbol table
mod_perl can then walk and grind the names and values of Perl
variables/structures through the Apache core config gears. Most of the
configurations directives can be represented as <CODE>$Scalars</CODE> or
@Lists. A <CODE>@List</CODE> inside these sections is simply converted into
a single-space delimited string for you inside. Here's an example:
<P>
<PRE> #httpd.conf
<Perl>
@PerlModule = qw(Mail::Send Devel::Peek);
#run the server as whoever starts it
$User = getpwuid($>) || $>;
$Group = getgrgid($)) || $);
$ServerAdmin = $User;
</Perl>
</PRE>
<P>
Block sections such as <Location></Location> are represented in
a %Hash, e.g.:
<P>
<PRE> $Location{"/~dougm/"} = {
AuthUserFile => '/tmp/htpasswd',
AuthType => 'Basic',
AuthName => 'test',
DirectoryIndex => [qw(index.html index.htm)],
Limit => {
METHODS => 'GET POST',
require => 'user dougm',
},
};
</PRE>
<P>
If a Directive can take say, two *or* three arguments you may push strings
and the lowest number of arguments will be shifted off the
<CODE>@List</CODE> or use array reference to handle any number greater than
the minimum for that directive push @Redirect, ``/foo'',
``http://www.foo.com/'';;
<P>
<PRE> push @Redirect, "/imdb", "<A HREF="http://www.imdb.com/"">http://www.imdb.com/"</A>;;;
</PRE>
<P>
<PRE> push @Redirect, [qw(temp "/here" "<A HREF="http://www.there.com"">http://www.there.com"</A>;;)];
</PRE>
<P>
Other section counterparts include %VirtualHost, <CODE>%Directory</CODE>
and %Files.
<P>
These are somewhat boring examples, but they should give you the basic
idea. You can mix in any Perl code your heart desires. See eg/httpd.conf.pl
and eg/perl_sections.txt in mod_perl distribution for some examples.
<P>
A tip for syntax checking outside of httpd:
<P>
<PRE> <Perl>
#!perl
#... code here ...
__END__
</Perl>
</PRE>
<P>
Now you may run perl -cx httpd.conf.
<P>
To configure this feature build with 'perl Makefile.PL PERL_SECTIONS=1'
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/18/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/control.html
Index: control.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Controlling and Monitoring the Server </TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Controlling and Monitoring the Server </H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Restarting_techniques">Restarting techniques</A>
<LI><A HREF="#How_restart_influences_the_mod_p">How restart influences the mod_perl namespace</A>
<LI><A HREF="#Using_apachectl_to_control_the_s">Using apachectl to control the server</A>
<LI><A HREF="#Single_Mode_Running">Single Mode Running</A>
<LI><A HREF="#Starting_a_personal_server_for_e">Starting a personal server for each developer</A>
<LI><A HREF="#Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A>
<LI><A HREF="#Log_Rotation">Log Rotation</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Restarting_techniques">Restarting techniques</A></H1></CENTER>
<P>
In all these techniques you will have to know the server PID (Process ID).
The easiest
<P>
You will notice many httpd_perl executables running on your system, but you
should not send signals to any of them except the parent, whose pid is in
the PidFile. That is to say you shouldn't ever need to send signals to any
process except the parent. There are three signals that you can send the
parent: TERM, HUP, and USR1.
<P>
We will concentrate here at the implications of sending these signals to
mod_perl server. To Read the complete doc at <A
HREF="http://www.apache.org/docs/stopping.html">http://www.apache.org/docs/stopping.html</A>
<DL>
<P><DT><STRONG><A NAME="item_TERM">TERM Signal: stop now</A></STRONG><DD>
<P>
Sending the TERM signal to the parent causes it to immediately attempt to
kill off all of its children. It may take it several seconds to complete
killing off its children. Then the parent itself exits. Any requests in
progress are terminated, and no further requests are served.
<P>
That's the moment that the accumulated END{} blocks will be executed!
<P><DT><STRONG><A NAME="item_HUP">HUP Signal: restart now</A></STRONG><DD>
<P>
Sending the HUP signal to the parent causes it to kill off its children
like in TERM but the parent doesn't exit. It re-reads its configuration
files, and re-opens any log files. Then it spawns a new set of children and
continues serving hits.
<P>
Server will rerun its config files. Flush all the compiled and preloaded
modules. Rerun any startup files. It's equal to starting a server after it
was stopped.
<P>
Note: If your configuration file has errors in it when you issue a restart
then your parent will not restart, it will exit with an error. See below
for a method of avoiding this.
<P><DT><STRONG><A NAME="item_USR1">USR1 Signal: graceful restart</A></STRONG><DD>
<P>
The USR1 signal causes the parent process to advise the children to exit
after their current request (or to exit immediately if they're not serving
anything). The parent re-reads its configuration files and re-opens its log
files. As each child dies off the parent replaces it with a child from the
new generation of the configuration, which begins serving new requests
immediately.
<P>
META: What's the difference between USR1 and HUP?
</DL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="How_restart_influences_the_mod_p">How restart influences the mod_perl namespace</A></H1></CENTER>
<P>
By default, if a server is restarted (ala kill -USR1 `cat logs/httpd.pid`),
Perl scripts and modules are not reloaded. To reload PerlRequire's,
PerlModule's, other <CODE>use()'d</CODE> modules and flush the
Apache::Registry cache, enable with this command:
<P>
<PRE> PerlFreshRestart On (in httpd.conf)
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Using_apachectl_to_control_the_s">Using apachectl to control the server</A></H1></CENTER>
<P>
apache's distribution provides a nice script to control the server. It's
called apachectl and it's being installed into the same location with
httpd. In our scenario - it's /usr/apps/sbin/httpd_perl/apachectl
<P>
Start httpd
<P>
<PRE> % /usr/apps/sbin/httpd_perl/apachectl start
</PRE>
<P>
Stop httpd
<P>
<PRE> % /usr/apps/sbin/httpd_perl/apachectl stop
</PRE>
<P>
Restart httpd if running by sending a SIGHUP or start if not running
<P>
<PRE> % /usr/apps/sbin/httpd_perl/apachectl restart
</PRE>
<P>
Do a graceful restart by sending a SIGUSR1 or start if not running
<P>
<PRE> % /usr/apps/sbin/httpd_perl/apachectl graceful
</PRE>
<P>
Do a configuration syntax test
<P>
<PRE> % /usr/apps/sbin/httpd_perl/apachectl configtest
</PRE>
<P>
See the next section for the implication of the above calls.
<P>
Replace the httpd_perl to httpd_docs in the above calls to get the control
over httpd_docs server.
<P>
There are other options for apachectl, use 'help' option to see them all
<P>
It's important to understand that this scriptmis based on the PID file
which is PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid. If you delete the
file by hand - the apachectl will fail to run.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Single_Mode_Running">Single Mode Running</A></H1></CENTER>
<P>
Many times while developing a new code, you will want to run the server in
the single process mode. See <A HREF="././porting.html#Sometimes_it_works_Sometimes_Not">Sometimes it works Sometimes Not</A> and <A HREF="././porting.html#Names_collisions_with_Modules_an">Names collisions with Modules and libs</A>
<P>
<PRE> % /usr/apps/sbin/httpd_perl/httpd_perl -X
</PRE>
<P>
When you execute the above the server will run in the fg (foreground) of
the shell you have called it from. So to kill you just kill it with Ctrl-C.
<P>
Note that in -X mode the server will run very slowly on fetching the
images. If you use Netscape while your server is running in single-process
mode, the ``KeepAlive'' feature gets in the way. Netscape tries to open
multiple connections and keep them open. Because there is only one server
process listening, each connection has to time-out before the next
succeeds. Turn off KeepAlive in httpd.conf to avoid this effect while
developing or you can press <STRONG>STOP</STRONG> after a few secs of run (assuming you use the image size params, so the
Netscape will be able to render the rest of the page).
<P>
In addition you should know that you will not see any control messages
(when running with -X), you generally see in the error_log that the parent
server writes: Like ``server started, server stopped and etc''. Since httpd
-X runs immediately as a child, so there is no controlling parent to write
all the status messages
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Starting_a_personal_server_for_e">Starting a personal server for each developer</A></H1></CENTER>
<P>
If you are the only developer working on the specific server:port - you
have no problems, since you have a complete control over the server. Now
many times you have a group of developers who need to concurently develop
their mod_perl scripts. It means that each one will want to get the control
over the server - to kill it, to run it in single server mode, to restart
it again and soon. As well to have to control over the log files and other
configuration like MaxClients and etc . You can workaround this problem by
preparing a few httpd.conf file and to force each developer to use:
<P>
<PRE> httpd_perl -f /path/to/httpd.conf
</PRE>
<P>
I've approached it in other way. I have used the -Dparameter startup option
of the server. I call my version of the server
<P>
<PRE> % http_perl -Dsbekman
</PRE>
<P>
At the end of the httpd.conf I wrote: # Personal development Server for
sbekman # sbekman use the server running on port 8000 <IfDefine
sbekman> Port 8000 PidFile
/usr/apps/var/httpd_perl/run/httpd.pid.sbekman ErrorLog
/usr/apps/var/httpd_perl/logs/error_log.sbekman Timeout 300 KeepAlive On
MinSpareServers 2 MaxSpareServers 2 StartServers 1 MaxClients 3
MaxRequestsPerChild 15 </IfDefine>
<P>
<PRE> # Personal development Server for userfoo
# userfoo use the server running on port 8001
<IfDefine userfoo>
Port 8001
PidFile /usr/apps/var/httpd_perl/run/httpd.pid.userfoo
ErrorLog /usr/apps/var/httpd_perl/logs/error_log.userfoo
Timeout 300
KeepAlive Off
MinSpareServers 1
MaxSpareServers 2
StartServers 1
MaxClients 5
MaxRequestsPerChild 0
</IfDefine>
</PRE>
<P>
So what we have achived with this technique is: A full control over
start/stop, number of childs, separate error log file, and different port.
Now I wouldn't get the call every few minutes - ``Stas, I'm going to
restart the server''.
<P>
To make things even more easier. (In the above technique, you have to
discover the PID of your parent httpd_perl process - written in
/usr/apps/var/httpd_perl/run/httpd.pid.userfoo) . We change the apachectl
script to do the work for us. We make a copy for each developer called
apachectl.username and we change 2 lines in script:
<P>
<PRE> PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid.sbekman
HTTPD='/usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman'
</PRE>
<P>
Ofcourse you think you can use only one control file and to know who is
calling by using uid, but since you have to be root to start the server -
it's not so simple.
<P>
The last thing was to let developers an option to run in single process
node by:
<P>
<PRE> /usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman -X
</PRE>
<P>
In addition to make life easier we decided to use relative links everywhere
in the static docs (including the calls to cgis). You will ask how using
the relative link you will get to the right server? Very simple - we have
utilized the mod_rewrite to solve our problems:
<P>
In access.conf of the httpd_docs server we have the following code: (you
have to configure your httpd_docs server with --enable-module=rewrite )
<P>
<PRE> # sbekman' server
# port = 8000
RewriteCond %{REQUEST_URI} ^/(perl|cgi-perl)
RewriteCond %{REMOTE_ADDR} 123.34.45.56
RewriteRule ^(.*) <A HREF="http://ourserver.com:8000/">http://ourserver.com:8000/</A>$1 [R,L]
# userfoo's server
# port = 8001
RewriteCond %{REQUEST_URI} ^/(perl|cgi-perl)
RewriteCond %{REMOTE_ADDR} 123.34.45.57
RewriteRule ^(.*) <A HREF="http://ourserver.com:8001/">http://ourserver.com:8001/</A>$1 [R,L]
# all the rest
RewriteCond %{REQUEST_URI} ^/(perl|cgi-perl)
RewriteRule ^(.*) <A HREF="http://ourserver.com:81/">http://ourserver.com:81/</A>$1 [R]
</PRE>
<P>
where IP numbers are then IPs of the developers they run the browser at. (I
have tried to use REMOTE_USER since we have all the users authenticated but
it didn't work for me)
<P>
So if I have a relative URL like /perl/test.pl written in some html or even
<A
HREF="http://ourserver.com/perl/test.pl">http://ourserver.com/perl/test.pl</A>
in my case (user at machine of sbekman) it will be redirected by httpd_docs
to <A
HREF="http://ourserver.com:8000/perl/test.pl">http://ourserver.com:8000/perl/test.pl</A>
<P>
Ofcourse you have another problem: The cgi generates some html, which
should be called again. If it generates a URL with hardcoded PORT the above
scheme will not work. There 2 solutions:
<P>
First to generate relative URL so it will reuse the technique above, with
redirect (which is trasparent for user) but it will not work if you have
something to POST (redirect looses all the data!)
<P>
Second to use a general config module which generates a correct full URL
according to REMOTE_USER, so if $ENV{REMOTE_USER} eq 'sbekman', I return <A
HREF="http://ourserver.com:8000/perl/">http://ourserver.com:8000/perl/</A>
as cgi_base_url. Again this will work if the user is authenticated.
<P>
All this good for development. It's better to use the full URLs in
production, since if you have a static form and the Action is relative but
the static document sits on another server, pressing form's submit will
cause a redirect to mod_perl server, but all the form's data will be lost
during the redirect.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A></H1></CENTER>
<P>
Many times you startoff with debugging your script by running it at your
favorite shell. Sometimes you encounter a very weird situation when script
runs from the shell but dies when called as cgi. The real problem lays in
the difference of the environment that's being used by your server and your
shell. An example can be a different perl path or having PERL5LIB env
variable which includes pathes that aren't in the <CODE>@INC</CODE> of the
perl compiled with mod_perl server and configured during the startup.
<P>
The best thing is to write a wrapper that emulates the exact environment of
the server, By deleting first the environment variables like PERL5LIB and
calling the same perl that it's being used by the server. Then setting the
environment identical to the server's by copying the perl run directives
from server startup and config files. It'll also allow you to remove
competely the first line of the script - since mod_perl skip it and wrapper
knows how to call the script
<P>
Below is the example of such a script. Note that we force the -wT when we
call the real script. (I have also added the ability to pass params, which
is not happen when you call the cgi from the web)
<P>
<PRE> #!/usr/apps/bin/perl -w
# This is a wrapper example
# It simulates the webserver environment by setting the @INC and other
# stuff, so what will run under this wrapper will run under web and
# vice versa.
#
# Usage: wrap.pl some_cgi.pl
#
BEGIN{
use vars qw($basedir);
$basedir = "/usr/apps";
# we want to make a complete emulation, so we must remove the
# user's environment
@INC = ();
</PRE>
<P>
<PRE> # local perl libs
push @INC, ("$basedir/lib/perl5/5.00502/aix",
"$basedir/lib/perl5/5.00502",
"$basedir/lib/perl5/site_perl/5.005/aix",
"$basedir/lib/perl5/site_perl/5.005",
);
}
use strict;
use <A HREF="File::Basename">File::Basename</A>;
# process the passed params
my $cgi = shift || '';
my $params = (@ARGV) ? join(" ", @ARGV) : '';
die "Usage:\n\t$0 some_cgi.pl\n" unless $cgi;
# Set the environment
my $PERL5LIB = join ":", @INC;
# if the path includes the directory we extract it and chdir there
if ($cgi =~ m|/|) {
my $dirname = dirname($cgi);
chdir $dirname or die "Can't chdir to $dirname: $! \n";
$cgi =~ m|$dirname/(.*)|;
$cgi = $1;
}
# run the cgi from the script's directory
# Note that we envoke warnings and Taintness ON!!!
system qq{$basedir/bin/perl -I$PERL5LIB -wT $cgi $params};
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Log_Rotation">Log Rotation</A></H1></CENTER>
<P>
A little bit offtopic but good to know.
<P>
To rotate the logs do:
<P>
<PRE> mv access_log access_log.renamed
kill -USR1 `cat httpd.pid`
sleep 10; # allow some children to complete requests and logging
# now it's safe to use access_log.renamed
.....
</PRE>
<P>
The effect of SIGUSR1 is detailed in: <A
HREF="http://www.apache.org/docs/stopping.html">http://www.apache.org/docs/stopping.html</A>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/19/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/debug.html
Index: debug.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Debugging techniques </TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Debugging techniques </H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Debug_Tracing">Debug Tracing</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Debug_Tracing">Debug Tracing</A></H1></CENTER>
<P>
To enable mod_perl debug tracing configure mod_perl with the PERL_TRACE
option:
<P>
<PRE> perl Makefile.PL PERL_TRACE=1
</PRE>
<P>
The trace levels can then be enabled via the <B>MOD_PERL_TRAC/&B;
environment variable which can contain any combination of:
<P>
<PRE> d - Trace directive handling during configuration read
s - Trace processing of perl sections
h - Trace Perl*Handler callbacks
g - Trace global variable handling, intepreter construction, END blocks, etc.
all - all of the above
</PRE>
<P>
add to httpd.conf:
<P>
PerlSetVar MOD_PERL_TRACE all
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/16/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/help.html
Index: help.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Help Seek and Futher Learning </TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Help Seek and Futher Learning </H1>
<P>
<HR WIDTH="100%"></P>
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#1">READ ME FIRST</A></LI>
<LI><A HREF="#2">mod_perl</A></LI>
<LI><A HREF="#3">perl </A></LI>
<LI><A HREF="#4">perl/CGI</A></LI>
<LI><A HREF="#5">apache </A></LI>
</UL>
<P>
<HR WIDTH="100%"></P>
<H3><A NAME="1"></A>READ ME FIRST</H3>
<P>If after reading this guide and other documents listed n this section,
you feel that your question is yet not answered, please ask the apache/mod_perl
mailing list to help you. But first try to browse the mailing list archive.
Most of the time you will find the answer for your question by searching
the mailing archive, since there is a big chance someone else already have
encountered the problem and found a solution for it. If you ignore this
advice, don't be surprised if your question will be left unanswered - it
bores people to answer the same question more than once. It doesn't mean
that you should avoid asking questions. Just don't abuse the available
help and <B>RTFM </B>before you call for <B>HELP</B>. (You have certainly
heard the infamous fable of the shepherd boy and the wolves)</P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B>
<HR WIDTH="100%"></P>
<H3><A NAME="2"></A>mod_perl</H3>
<UL>
<LI><A HREF="perl.apache.org">perl.apache.org </A>- mod_perl home </LI>
<LI><A HREF="www.modperl.com">www.modperl.com</A> - This is the home site
of The Apache Modules Book, a book about creating Web server modules using
the Apache API, written by Lincoln Stein and Doug MacEachern.</LI>
<LI><A HREF="http://perl.apache.org/dist/cgi_to_mod_perl.html">Quick guide
</A>for moving from CGI to mod_perl. </LI>
<LI>Frank Cringle's <A HREF="http://perl.apache.org/faq/">mod_perl FAQ</A></LI>
<LI>Vivek Khera's <A HREF="http://perl.apache.org/tuning/">mod_perl performance
tuning guide</A></LI>
<LI>Doug MacEachern's <A HREF="http://perl.apache.org/src/mod_perl.html">mod_perl
plugin reference guide</A>. </LI>
<LI><A HREF="http://perl.apache.org/dist/mod_perl_traps.html">mod_perl_traps,</A>
common traps and solutions for mod_perl users. </LI>
<LI><A HREF="http://www.refcards.com">mod_perl Quick Reference
Card</A>
(Apache and other refcards are available from this link</LI>
<LI>mod_perl mailing list</LI>
<P><B>The Apache/Perl mailing list (modperl@apache.org) is available for
mod_perl users and developers to share ideas, solve problems and discuss
things related to mod_perl and the Apache::* modules.</B> To subscribe
to this list, send mail to majordomo@apache.org with the string "subscribe
modperl" in the body. </P>
<P><B>Searchable </B>mod_perl mailing list<B> <A HREF="http://forum.swarthmore.edu/epigone/modperl">archive</A>
</B>by Ken Williams. </P>
</UL>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B>
<HR WIDTH="100%"></P>
<H3><A NAME="3"></A>Perl </H3>
<UL>
<LI><A HREF="http://www.perl.com/CPAN/doc/FAQs/FAQ/PerlFAQ.html">The Perl
FAQ </A></LI>
<LI><A HREF="http://www.perl.com/">www.perl.com</A></LI>
<LI><A HREF="http://www.tpj.com/">The Perl Journal </A></LI>
<LI><A HREF="http://world.std.com/~swmcd/steven/perl/module_mechanics.html">Perl
Module Mechanics </A>- This page describes the mechanics of creating, compiling,
releasing and maintaining Perl modules. </LI>
</UL>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B>
<HR WIDTH="100%"></P>
<H3><A NAME="4"></A>Perl/CGI</H3>
<UL>
<LI><A HREF="http://www.perl.com/CPAN/doc/FAQs/cgi/perl-cgi-faq.html">Perl/CGI
FAQ </A></LI>
<LI><A HREF="http://www.eprotect.com/stas/TULARC/webmaster/myfaq.html">Answers
to some bothering Perl and Perl/CGI questions</A></LI>
<LI><A HREF="http://www.perl.com/CPAN/doc/FAQs/cgi/idiots-guide.html">Idiot's
Guide to CGI programming </A></LI>
<LI><A HREF="http://www.genome.wi.mit.edu/WWW/faqs/cgi/www-security-faq.html">WWW
Security FAQ </A></LI>
<LI><A HREF="http://www.gunther.web66.com/FAQS/taintmode.html">CGI/Perl
Taint Mode FAQ</A> (by Gunther Birznieks)</LI>
</UL>
<H3><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B>
<HR WIDTH="100%"></H3>
<H3><A NAME="5"></A>Apache </H3>
<UL>
<LI><A HREF="http://www.apache.org">Apache Project's Home</A></LI>
<LI><A HREF="http://www.ford-mason.co.uk/resources/refcards/apache.html">Apache
Quick Reference Card</A></LI>
<LI><A HREF="http://www.apache.org/docs/misc/FAQ.html">The Apache FAQ</A></LI>
<LI><A HREF="http://www.apache.org/docs/">Apache Server Documentation</A></LI>
</UL>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B>
<HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR></TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER><B><FONT SIZE=-1>Written by <A HREF="mailto:sbekman@iil.intel.com">Stas
Bekman</A>.<BR>
Last Modified at 11/09/1998 </FONT></B></TD>
<TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD><FONT SIZE=-2>Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission. </FONT> </TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/index.html
Index: index.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>Mod Perl Developer's Mini Guide</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>Mod Perl Developer's Mini Guide</H1>
<CENTER><P><B>Deploying apache/mod_perl accelerator to give a rocket speed
to your perl cgi-bin scripts.</B></P></CENTER>
<P>
<HR WIDTH="100%"></P>
<H3><FONT SIZE=-1>Table of Contents:</FONT></H3>
<UL>
<LI><A HREF="intro.html">Introduction, Incentives and Credits.</A></LI>
<LI><A HREF="start.html">Getting Started with mod_perl.</A></LI>
<LI><A HREF="scenario.html">Real World scenario</A> (the rest of the docs
are based and explained upon this scenario).</LI>
<LI><A HREF="config.html">Server Configuration</A>.</LI>
<LI><A HREF="control.html">Controlling and Monitoring the Server </A>(starting/stopping,
modules reloading, killing and etc...).</LI>
<LI><A HREF="status.html">Seeing the Unseen: Peeking into the Server Inwards</A></LI>
<LI><A HREF="porting.html">cgi2mod_perl Porting and Coding guidelines.</A></LI>
<LI><A HREF="obvious.html">What is obvious for others but not for you</A>.</LI>
<LI><A HREF="warnings.html">Warnings and Errors you see: Were do they
come from and How to fix them</A>? </LI>
<LI><A HREF="debug.html">Debugging techniques</A></LI>
<LI><A HREF="snippets.html">Code Snippets</A> (Usefull Code Snippets)</LI>
<LI><A HREF="performance.html">Making it even faster.</A> Performance discussion.
DB connections and more.(startup with modules preloading , opening DB connections
on schild's startup, global variables and more ).</LI>
<LI><A HREF="help.html">Help Seek and Futher Learning</A></LI>
</UL>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR></TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER><B><FONT SIZE=-1>Written by <A HREF="mailto:sbekman@iil.intel.com">Stas
Bekman</A>.<BR>
Last Modified at 11/09/1998 </FONT></B></TD>
<TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90></A>
</TD>
<TD><FONT SIZE=-2>Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission. </FONT> </TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/intro.html
Index: intro.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl mini-guide: Introduction, Incentives and Credits</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>Introduction,
Incentives and Credits</H1>
<P>
<HR WIDTH="100%"></P>
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#1">What is mod_perl</A></LI>
<LI><A HREF="#2">What is covered in this document</A></LI>
<LI><A HREF="#3">Sources and Acknowlegements</A></LI>
</UL>
<P>
<HR WIDTH="100%"></P>
<H3 ALIGN=CENTER><A NAME="1"></A>What is mod_perl</H3>
<P>The Apache/Perl integration project brings together the full power of
the Perl programming language and the Apache HTTP server. With mod_perl
it is possible to write Apache modules entirely in Perl. In addition, the
persistent interpreter embedded in the server avoids the overhead of starting
an external interpreter, the penalty of Perl start-up time and loading
and compiling the modules and the scripts. </P>
<P>The primary advantages of mod_perl are power and speed. You have full
access to the inner-workings of the web server and can intervene at any
stage of request-processing. This allows for customized processing of (to
name just a few of the phases) URI->filename translation, authentication,
response generation and logging. There is very little run-time overhead.
In particular, it is not necessary to start a separate process, as is often
done with web-server extensions. The most wide-spread such extension mechanism,
the Common Gateway Interface (CGI), can be replaced entirely with perl-code
that handles the response generation phase of request processing. Mod_perl
includes 2 general purpose modules for this purpose (Apache::Registry)
that can transparently run existing perl CGI scripts and Apache::PerlRun,
which does a similar job but allows you to run dirty (to some extent) written
scripts.</P>
<P>Many people wonder and ask "How much of a performance improvement
does mod_perl give?". Well, it all depends on what you're doing with
mod_perl and possibly who you ask. People report speed boosts from 200%
to 2000%. The best way to measure is to try it and see for yourself!
(see <A HREF="http://perl.apache.org/tidbits.html">TidBits </A>and <A HREF="http://perl.apache.org/stories/">Stories
</A>pages for the facts)</P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B>
<HR WIDTH="100%"></P>
<H3 ALIGN=CENTER><A NAME="2"></A>What is covered in this document</H3>
<P>This document was writtten to help you to start using the mod_perl as
soon as possible and with as less as possible obstacles. It includes an
information about installation and configuration of perl and apache
webserver and goes deeply into an issues of writing and porting the perl
scripts for mod_perl. Note, that it doesn't enter the big world of using
the Perl API or C API. You will find the Pointers covering these topics at
<A HREF="help.html">Help Seek and Learning more</A> section of this document.<B>
This guide tries to cover the most of the Apache::Registry and Apache::PerlRun.</B></P>
<P>It's assumed that you know the basics of building and installing of
perl and apache
(If you don't just read the INSTALL docs coming with distribution of each
package). However you will find in the document specific perl and
apache related installation and
configuration notes, which will help you to sucessfuly
complete the mod_perl installation.</P>
<P>If after reading this guide and other documents listed at <A HREF="help.html">Help
section</A>, you feel that your question is yet not answered, please ask
the apache/mod_perl mailing list to help you. But first try to browse the
mailing list archive. Most of the time you will find the answer for your
question by searching the mailing archive, since there is a big chance
someone else already have encountered the problem and found a solution
for it. If you ignore this advice, don't be surprised if your question
will be left unanswered - it bores people to answer the same question more
than once (twice?). It doesn't mean that you should avoid asking questions. Just
don't abuse the available help and <B>RTFM </B>before you call for <B>HELP</B>.
(You have certainly heard the infamous fable of the shepherd boy and the
wolves)</P>
<P>If you find incorrect details, my grammar mistakes or you want to contribute
to this document please fell free to send me an <A HREF="mailto:sbekman@iil.intel.com">email</A>.</P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B>
<HR WIDTH="100%"></P>
<H3 ALIGN=CENTER><A NAME="3"></A>Sources and Acknowledgements</H3>
<P>This document is based on:</P>
<UL>
<LI>Frank Cringle's <A HREF="http://perl.apache.org/faq/">mod_perl FAQ</A></LI>
<LI>Vivek Khera's <A HREF="http://perl.apache.org/tuning/">mod_perl performance
tuning guide</A></LI>
<LI>Doug MacEachern's <A HREF="http://perl.apache.org/src/mod_perl.html">mod_perl
plugin reference guide</A>. </LI>
<LI><A HREF="http://perl.apache.org/dist/cgi_to_mod_perl.html">Quick guide
</A>for moving from CGI to mod_perl. </LI>
<LI><A HREF="http://perl.apache.org/dist/mod_perl_traps.html">mod_perl_traps,</A>
common traps and solutions for mod_perl users. </LI>
<LI>Answers to some of the questions posted to <A HREF="mailto:modperl@apache.org">Apache/Perl
mailing list</A></LI>
<LI>My personal experience with mod_perl</LI>
</UL>
<P>As I said, I've quoted many unformation snippets from FAQs and emails,
and I didn't credit people after each quote in the guide. I didn't mean to
take the credits for myself, it's just that I've tried to keep
track of names, and became lost, so I prefered not to credit at
all in the guide, but to centralize it here. If you think that
you want your name to show up under your original quote that I
have used, please Tell me and I'll add it for you.<P>
<P> Credits go to ( alphabetically sorted );
<UL>
<LI>Andreas J. Koenig
<LI>Ask Bjoern Hansen
<LI>Brian Moseley
<LI>Chad K. Lewis
<LI>Doug Bagley
<LI>Doug MacEachern
<LI>Edmund Mergl
<LI>Eric Cholet
<LI>Frank Cringle
<LI>G.Richter
<LI>Gunther Birznieks
<LI>Howard Jones
<LI>Jeff Baker
<LI>Jeff Rowe
<LI>Jon Orwant
<LI>Ken Williams
<LI>Leslie Mikesell
<LI>Lincoln Stein
<LI>Mike Fletcher
<LI>Nathan Torkington
<LI>Ralf Engelschall
<LI>Randal Schwartz
<LI>Vivek Khera
<LI>
<LI>Did I miss you? Tell me!
</UL>
</P>
<P>I want to thank all the people who donated their time and efforts
to made this amazing idea of mod_perl to become reality. It includes Doug
MacEachern, the author of mod_perl and all the developers who contributed
bug patches , modules and help. And ofcourse the numeral unseen users who
helped to find the bugs and advocate mod_perl around the world.</P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B>
<HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR></TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER><B><FONT SIZE=-1>Written by <A HREF="mailto:sbekman@iil.intel.com">Stas
Bekman</A>.<BR>
Last Modified at 11/19/1998 </FONT></B></TD>
<TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD><FONT SIZE=-2>Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission. </FONT> </TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/obvious.html
Index: obvious.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: What is obvious for others but not for you </TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
What is obvious for others but not for you </H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Coverage">Coverage</A>
<LI><A HREF="#my_scoped_variable_in_the_nest">my() scoped variable in the nested subroutine</A>
<LI><A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
<UL>
<LI><A HREF="#Restarting_the_server">Restarting the server</A>
<LI><A HREF="#Using_Apache_StatINC">Using Apache::StatINC</A>
<LI><A HREF="#Reloading_only_specific_files">Reloading only specific files</A>
</UL>
<LI><A HREF="#Compiled_Regular_Expressions">Compiled Regular Expressions </A>
<LI><A HREF="#Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</A>
<LI><A HREF="#_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
<P>
This document describes a ``special'' traps of running your plain cgis
under Apache::Registry and Apache::PerlRun
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="my_scoped_variable_in_the_nest">my() scoped variable in the nested subroutine</A></H1></CENTER>
<P>
When you write a code like:
<P>
<PRE> #!perl -w
my $x;
sub y {
$x
}
</PRE>
<P>
there is no problem. But when you write:
<P>
<PRE> #!perl -w
sub x {
my $x;
sub y {
$x
}
}
</PRE>
<P>
it produces this warning:
<P>
<PRE> Value of $x will not stay shared at - line 5.
</PRE>
<P>
The tone of this message is definite because the code *will* fail if
&amp;x is called more than once. NOTE: Subroutines defined inside
BEGIN{} and END{} cannot trigger this message, since each BEGIN{} and END{}
is known to be called exactly once. (To understand why, read about the
closures at perlref or perlfaq 13.12)
<P>
Also, this slightly different code:
<P>
<PRE> #!perl -w
sub x {
my $x;
sub y {
sub { $x }
}
}
</PRE>
<P>
produces this warning:
<P>
<PRE> Value of $x may be unavailable at - line 5.
</PRE>
<P>
This message is less definite because the code can work correctly, if
&amp;y is called only from inside &amp;x.
<P>
(this was partitially extracted from perl5-porters post)
<P>
Now hold on, you ask what it has to do with your cgi script?
<P>
That's exactly the point that is not obvous. Apache::Registry wraps your
code into a sub! You heard it right. So all your code's subs are nested.
And while you don't see it, your code actually is the same as the simple
snippet above. And all the behavior described above applies to your code!
<P>
A solution?
<P>
<PRE> use vars qw($x $a); at the top of you code
</PRE>
<P>
META: more solutions? (Code inside packages?)
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
<P>
When you develop your plain cgi scripts you just change the code, and rerun
the cgi in your browser. Since the script wasn't staying in the memory, the
next time you call it - server recompile it from scratch so all the changes
you apply are immediatley taking the expected effect.
<P>
The situation is different with Apache::Registry. Since the whole idea was
to get the maximum performance from the server. By default server wouldn't
spend the time to go and check whether the code has been changed. It
assumes that it wasn't, thus saving a few milisecs to stat the file (And if
you have many of them it takes more time). The only check that is being
done is whether your main script has been changed. So if you have only one
script that doesn't requre or use other Perl Modules (packages) there is
nothing new about it. The files you <CODE>use()</CODE> or
<CODE>require()</CODE> aren't being checked at all. So what are the
workarounds?
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
<P>
See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Using_Apache_StatINC">Using Apache::StatINC</A></H2></CENTER>
<P>
After restarting the server for about 100 times you will be tired and will
look for another solutions. Here comes for a help the Apache::StatINC
module.
<P>
Read its pod pages, but beware of the following note: Only the modules
located in <CODE>@INC</CODE> are being reloaded on change, and you can
change the <CODE>@INC</CODE> only before the server has been started.
Whatever you do in you scripts/modules which are being
<CODE>required()</CODE> after the server startup will not take an effect on
@INC. When you do use lib <CODE>qw(foo/bar);</CODE> the <CODE>@INC</CODE>
is being changed only for the time the code is being parsed. When it's over
the <CODE>@INC</CODE> is being reset to its original value. To make sure
that you have set a correct <CODE>@INC</CODE> fetch <A
HREF="http://your.perl.server/perl-status?inc">http://your.perl.server/perl-status?inc</A>
and watch the bottom of the page. (I consider you have configured the
<Location /perl-status> section in httpd.conf as modperl docs shows.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Reloading_only_specific_files">Reloading only specific files</A></H2></CENTER>
<P>
However checking all the Modules in <CODE>@INC</CODE> can add a big
overhead to server response times, and you certainly wouldn't want
Apache::StatINC module to be enabled in your production site's
configuration. But sometimes you want to have some Configuration file
(module) to be reloaded without restarting the whole server. For this you
will have to add something like this in your code:
<P>
Assume that you started your scripts with:
<P>
<PRE> use lib "/some/private/path";
use Foo::Bar qw(:subs);
</PRE>
<P>
Now to make a modification test and reload at runtime you have to use
something like this:
<P>
<PRE> # child's global variable to keep the timestamps
use vars qw(%MODIFIED);
my $my_lib_root = "/some/private/path";
my $conf = "Foo/Bar.pm";
my $conf_path = "$my_lib_root/$conf";
# set modification time if it wasn't set before
# Note: Use (stat $conf_path)[9] instead of -M test, if you reset
# time with $^M=time
$MODIFIED{$conf} ||= -M $conf_path;
# now check whether it was changed (assuming the above wasn't
# performed in this session
if ($MODIFIED{$conf} != -M $conf_path){
# only if deleted from %INC the require will be called below
delete $INC{$conf};
# this should be safe since @INC is being reset after we leave
# the script, or you can skip this stage and require the script
# with full path, remember that @INC now is different from the
# one you have had when the script has been called at first time
unshift @INC,$my_lib_root;
# reread the file : use() wouldn't work here since it's compile time directive
require Foo::Bar;
# now export the symbols (if you need them back :)
import Foo::Bar qw(:subs);
# Update the MODIFICATION times
$MODIFIED{$conf} = -M $conf_path;
}
</PRE>
<P>
You will want to add debug printings to test this code in your application
<P>
Read also use versus require article for more info.
(http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require)
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Compiled_Regular_Expressions">Compiled Regular Expressions</A></H1></CENTER>
<P>
When using a regular expression that contains an interpolated Perl
variable, if it is known that the variable (or variables) will not vary
during the execution of the program, a standard optimization technique
consists of adding the o modifier to the regexp pattern, to direct the
compiler to build the internal table once, for the entire lifetime of the
script, rather than every time the pattern is executed. Consider:
<P>
<PRE> my $pat = '^foo$'; # likely to be input from an HTML form field
foreach( @list ) {
print if /$pat/o;
}
</PRE>
<P>
This is usually a big win in loops over lists, or when using grep or map.
<P>
In long-lived mod_perl scripts, however, this can pose a problem if the
variable changes according to the invocation. The first invocation of a
fresh httpd child will compile the table and perform the search correctly,
however, all subsequent uses by the httpd child will continue to match the
original pattern, regardless of the current contents of the Perl variables
the pattern is dependent on. Your script will appear broken.
<P>
There are two solutions to this problem.
<P>
The first is to use eval q//, to force the code to be evaluated each time.
Just make sure that the eval block covers the entire loop of processing,
and not just the pattern match itself.
<P>
The above code fragment would be rewritten as:
<P>
<PRE> my $pat = '^foo$';
eval q{
foreach( @list ) {
print if /$pat/o;
}
}
</PRE>
<P>
Just saying
<P>
<PRE> eval q{ print if /$pat/o; };
</PRE>
<P>
is going to be a horribly expensive proposition.
<P>
You use this approach if you require more than one pattern match operator
in a given section of code. If the section contains only one operator (be
it an m// or s///), you can rely on the property of the null pattern, that
reuses the last pattern seen. This leads to the second solution, which also
eliminates the use of eval.
<P>
The above code fragment becomes:
<P>
<PRE> my $pat = '^foo$';
"something" =~ /$pat/; # dummy match (MUST NOT FAIL!)
foreach( @list ) {
print if //;
}
</PRE>
<P>
The only gotcha is that the dummy match that boots the regular expression
engine must absolutely, positively succeed, otherwise the pattern will not
be cached, and the // will match everything. If you can't count on fixed
text to ensure the match succeeds, you have two possibilities.
<P>
If you can guaranteee that the pattern variable contains no meta-characters
(things like *, +, ^, $...), you can use the dummy match:
<P>
<PRE> "$pat" =~ /\Q$pat\E/; # guaranteed if no meta-characters present
</PRE>
<P>
If there is a possibility that the pattern can contain meta-characters, you
should search for the pattern or the unsearchable \377 character as
follows:
<P>
<PRE> "\377" =~ /$pat|^[\377]$/; # guarenteed if meta-characters present
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</A></H1></CENTER>
<P>
Running in httpd -X mode. (good only for testing during development phase)
<P>
You want to test your application that it handles correctly the global
variables. (The less you have them the better, but sometimes you just have
to have a few of them). It's hard to do with multiply servers serving your
cgi since each child can has a different value for its global variables.
Imagine that you have a <CODE>random()</CODE> sub that returns a random
number and you have the following script.
<P>
use vars <CODE>qw($num);</CODE> <CODE>$num</CODE> ||=
<CODE>random();</CODE> print ++$num;
<P>
Running this script in multiply server environment will result in something
like 1,9,4,19 (number per reload). While if you run in httpd -X single
server mode you will get 2,3,4,5...
<P>
META: (Is it representing enough?)
<P>
But don't get too obsessive wuth this mode, since working only in single
server mode sometimes hides problems that show up when you switch to
multiserver mode. Assume the following code:
<P>
Application that allows you to change the configuration at the run time.
Let's say the script produce a form to change the background color of the
page. (It's not a good idea but for the sake of potential problem
presentation we will assume that we don't write down the change on the
disk). So you have typed in a new color , and as a respond you print back
the html with a new color - you think that's it! It was so simple. And if
you keep running in single server mode you will never notice that you have
a problem... If you run the same code in the multiserver environment ,
after you submit the color change you will get the result as expected, but
when you will call the same URL again (not reload!) most of the chances
that you will get back the old color, since except the child who processed
the color change request no one knows about their global variable change.
Just remember that childs can't share information, but the stuff they
inherited from parent on their load.
<P>
Also note that since server run in single mode - If the output returns HTML
with IMG tags, the load of these will take a lot of time (read apache docs
of httpd -X to learn why).
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A></H1></CENTER>
<P>
Under mod_perl files that have been created after the server's (child?)
startup are being reported with negative age with -M (-C -A) test. This is
obvious if you remember that you will get the negative result if the server
was started before the file was created and it's a normal behaviour with
any perl.
<P>
If you want to have -M test to count the time relative to the current
request, you should reset the $^T variable as with any other perl script.
Just add <CODE>$^T = time;</CODE> at the beginning of the scripts.
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/19/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/performance.html
Index: performance.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Making it even Faster </TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Making it even Faster </H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
<LI><A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>
<LI><A HREF="#Avoid_Importing_Functions">Avoid Importing Functions</A>
<LI><A HREF="#Reducing_the_Memory_Usage">Reducing the Memory Usage</A>
<LI><A HREF="#Limiting_the_size_of_the_process">Limiting the size of the processes</A>
<LI><A HREF="#Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A>
<LI><A HREF="#Benchmarks">Benchmarks </A>
<LI><A HREF="#Persistent_DB_Connections">Persistent DB Connections</A>
<LI><A HREF="#Real_Numbers">Real Numbers</A>
<LI><A HREF="#Profiling">Profiling</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A></H1></CENTER>
<P>
Use the PerlRequire and PerlModule directives to load commonly used modules
such as CGI.pm, DBI, etc., when the server is started. On most systems,
server children will be able to share this space.
<P>
You can also put the standard <CODE>use Foo;</CODE> into the startup-file.
<P>
CGI.pm is a special one, you will want to put into a startup-file:
<P>
<PRE> use CGI ();
CGI->compile(':all');
</PRE>
<P>
If you use DBI for DB connections, you can preopen a connections to DB for
each child with Apache::DBI.
<P>
<PRE> use Apache::DBI ();
Apache::DBI->connect_on_init("DBI:mysql:test", '','', {
RaiseError => 1,
PrintError => 1,
AutoCommit => 1,
};
</PRE>
<P>
See also <A HREF="#DB_Persistant_Connections">DB Persistant Connections</A>
<P>
You can also preload the Registry scripts. See <A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>.
<P>
See also: <A HREF="#Real_Numbers">Real Numbers</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Preload_Registry_Scripts">Preload Registry Scripts</A></H1></CENTER>
<P>
Apache::RegistryLoader compiles Apache::Registry scripts at server startup.
It can be a good idea to preload these as well. So the code will be shared
among the child servers.
<P>
example of use at modperl.com in a PerlRequire'd file:
<P>
<PRE> use <A HREF="File::Find">File::Find</A> 'finddepth';
use Apache::RegistryLoader ();
{
my $perl_dir = "perl/";
my $rl = Apache::RegistryLoader->new;
finddepth(sub {
return unless /\.pl$/;
my $url = "/$<A HREF="File::Find::dir/">File::Find::dir/</A>$_";
print "pre-loading $url\n";
my $status = $rl->handler($url);
unless($status == 200) {
warn "pre-load of `$url' failed, status=$status\n";
}
}, $perl_dir);
}
</PRE>
<P>
See also: perldoc Apache::RegistryLoader
<P>
You have to check whether it makes any good for you though, I did some
testing [ <A HREF="#Real_Numbers">Real Numbers</A> ], and it seems that it takes more memory than when the scripts is being
called from the child - This is only a first impression and needs better
investigation. If you aren't concerned about few scripts invocations which
will take some time to respond while they load the code, you might not need
it all!
<P>
See also <A HREF="././porting.html#BEGIN_blocks">BEGIN blocks</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Avoid_Importing_Functions">Avoid Importing Functions</A></H1></CENTER>
<P>
When possible, avoid importing of a module functions into your namespace.
The aliases which are created can take up quite a bit of space. Try to use
method interfaces and fully qualified Package::function names instead.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Reducing_the_Memory_Usage">Reducing the Memory Usage</A></H1></CENTER>
<P>
One of the important issues in improving the performance is memory usage
reduce - the less memory server uses - the more server processes you can
start - the more performance you have (from the user point of view - the
respond speed )
<P>
See <A HREF="././porting.html#Global_Variables">Global Variables</A>
<P>
See <A HREF="././porting.html#Memory_leakages">Memory "leakages"</A>
<P>
Joel Wagner reports that calling an undefined subroutine in a module can
cause a tight loop that consumes all memory. Here is a way to catch such
errors. Define an autoload subroutine
<P>
<PRE> sub UNIVERSAL::AUTOLOAD {
my $class = shift;
warn "$class can't \$UNIVERSAL::AUTOLOAD!\n";
}
</PRE>
<P>
It will produce a nice error in error_log, giving the line number of the
call and the name of the undefined subroutine.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Limiting_the_size_of_the_process">Limiting the size of the processes</A></H1></CENTER>
<P>
Apache::SizeLimit allows you to kill off Apache httpd processes if they
grow too large. see perldoc Apache::SizeLimit for more details.
<P>
By using this module, you should be able to discontinue using the Apache
configuration directive MaxRequestsPerChild, although for some folks, using
both in combination does the job.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A></H1></CENTER>
<P>
Apache::Resource uses the BSD::Resource module, which uses the C function
setrlimit to set limits on system resources such as memory and cpu usage.
<P>
See perldoc Apache::Resource for more info.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Benchmarks">Benchmarks</A></H1></CENTER>
<P>
How much faster is mod_perl that CGI? There are many ways to benchmark the
two, see the benchmark/ directory for some examples.
<P>
META: complete!
<P>
for heavy scripts use Benchmark for very fast scripts use Time::HiRes
<P>
<PRE> use Time::HiRes qw(gettimeofday tv_interval);
</PRE>
<P>
<PRE> my $start_time = [ gettimeofday ];
&sub_that_takes_a_teeny_bit_of_time()
my $end_time = [ gettimeofday ];
my $elapsed = tv_interval($start_time,$end_time);
</PRE>
<P>
<PRE> print "the sub took $elapsed secs."
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Persistent_DB_Connections">Persistent DB Connections</A></H1></CENTER>
<P>
Another popular use of mod_perl is to take advantage of it's persistance to
maintain open database connections. The basic idea goes like so:
<P>
<PRE> #Apache::Registry script
use strict;
use vars qw($dbh);
</PRE>
<P>
<PRE> $dbh ||= SomeDbPackage->connect(...);
</PRE>
<P>
Since <CODE>$dbh</CODE> is a global variable for the child, once the child
has opened the connection it will use it over and over again, unless you
perform <CODE>disconnect().</CODE>
<P>
Be carefull to use different names for handlers if you open connection to
different Databases!
<P>
Apache::DBI - allows to make a persistent database connection. With this
module enabled every connect request to plain DBI module will be forwarded
to the Apache::DBI module. This looks if a database handle from a previous
connect request is already stored and if this handle is still valid using
the ping method. If these two conditions are fulfilled it just returns the
database handle. If there is no appropriate database handle or if the ping
method fails, a new connection is established and the handle is stored for
later re-use. <STRONG>There is no need to delete the disconnect statements from your
code</STRONG>. They won't do anything because the Apache::DBI module overloads the
disconnect method with a NOP.
<P>
The usage is simple: httpd.conf ---------- PerlModule Apache::DBI It is
important, to load this module before any other ApacheDBI module !
<P>
<PRE> ascript.perl
------------
use DBI;
use strict;
my $dbh = DBI->connect( 'DBI:mysql:database', 'user', 'password',
{ autocommit => 0 }
) || die $DBI::errstr;
</PRE>
<P>
<PRE> ...rest of program
</PRE>
<P>
The module provides the additional method:
<P>
<PRE> Apache::DBI->connect_on_init($data_source, $username, $auth, \%attr)
</PRE>
<P>
This can be used as a simple way to have apache children establish
connections on server startup. This call should be in a startup file
(PerlModule, <Perl> or PerlRequire). It will establish a connection
when a child is started in that child process. See the Apache::DBI manpage
to see the requrements for this method.
<P>
However be warned that some old DBD drivers aren't supporting this feature
(ping method), so check the documentation of the driver you use.
<P>
Another problem are timeouts: some databases disconnect the client after a
certain time of inactivity. ping method ensures that this will not happen.
Some DBD drivers don't have this method, check the Apache::DBI manpage to
see how to write a ping method.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Real_Numbers">Real Numbers</A></H1></CENTER>
<P>
I have conducted a few tests to benchmark the memory usage when some
modules are preloaded. First set of tests checks the memory use with
Library Perl Module preload (only CGI.pm). The second set checks the
compile method of CGI.pm. The third test checks benefit the the Library
Perl Module preload but a few of them (too see more memory saved) and also
the effect of precompiling the Registry modules with
Apache::RegistryLoader.
<P>
Summary: 1. Library Perl Modules Preloading gave a good results everywhere.
2. compile method of CGI seems to make things worse (may be the speed is
better?) 3. Apache::RegistryLoader might made the script load faster on the
first request after the child has just started but the memory usage was
worse!!! See the numbers by yourself.
<P>
HW/SW: The server is apache 1.3.2, mod_perl 1.16 running on AIX 4.1.5
<P>
--------------------------------------------------------------------------------
<P>
1. In the first test was used a script:
<P>
<PRE> use strict;
use CGI ();
my $q = new CGI;
print $q->header;
print $q->start_html,$q->p("Hello");
</PRE>
<P>
<Server restarted>
<P>
Before the CGI.pm preload: (No other modules preloaded)
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 87004 0.0 0.0 1060 1524 - A 16:51:14 0:00 httpd
httpd 240864 0.0 0.0 1304 1784 - A 16:51:13 0:00 httpd
</PRE>
<P>
After running a script which uses CGI's methods (no imports):
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 188068 0.0 0.0 1052 1524 - A 17:04:16 0:00 httpd
httpd 86952 0.0 1.0 2520 3052 - A 17:04:16 0:00 httpd
</PRE>
<P>
Observation: child httpd has grown up by 1268K
<P>
<Server restarted>
<P>
After the CGI.pm preload:
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 240796 0.0 0.0 1456 1552 - A 16:55:30 0:00 httpd
httpd 86944 0.0 0.0 1688 1800 - A 16:55:30 0:00 httpd
</PRE>
<P>
after running a script which uses CGI's methods (no imports): USER PID
<CODE>%CPU</CODE> <CODE>%MEM</CODE> SZ RSS TTY STAT STIME TIME COMMAND root
86872 0.0 0.0 1448 1552 - A 17:02:56 0:00 httpd httpd 187996 0.0 1.0 2808
2968 - A 17:02:56 0:00 httpd
<P>
Observation: child httpd has grown up by 1168K, 100K less then without
preload - good!
<P>
<Server restarted>
<P>
After CGI.pm preloaded and compiled with CGI->compile(':all');
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 86980 0.0 0.0 2836 1524 - A 17:05:27 0:00 httpd
httpd 188104 0.0 0.0 3064 1768 - A 17:05:27 0:00 httpd
</PRE>
<P>
After running a script which uses CGI's methods (no imports):
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 86980 0.0 0.0 2828 1524 - A 17:05:27 0:00 httpd
httpd 188104 0.0 1.0 4188 2940 - A 17:05:27 0:00 httpd
</PRE>
<P>
Observation: child httpd has grown up by 1172K No change! So what does
CGI->compile(':all') helps? I guess it helps if you import the symbols
(subs) rather you use the methods
<P>
--------------------------------------------------------------------------------
2. I have tried the second test to find it. I run the script:
<P>
use strict; use CGI <CODE>qw(:all);</CODE> print
header,start_html,p(``Hello'');
<P>
<Server restarted>
<P>
After CGI.pm preloaded and NOT compiled with CGI->compile(':all');
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 17268 0.0 0.0 1456 1552 - A 18:02:49 0:00 httpd
httpd 86904 0.0 0.0 1688 1800 - A 18:02:49 0:00 httpd
</PRE>
<P>
After running a script which imports symbols, all of them
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 17268 0.0 0.0 1448 1552 - A 18:02:49 0:00 httpd
httpd 86904 0.0 1.0 2952 3112 - A 18:02:49 0:00 httpd
</PRE>
<P>
Observation: child httpd has grown up by 1264K
<P>
<Server restarted>
<P>
After CGI.pm preloaded and compiled with CGI->compile(':all');
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 86812 0.0 0.0 2836 1524 - A 17:59:52 0:00 httpd
httpd 99104 0.0 0.0 3064 1768 - A 17:59:52 0:00 httpd
</PRE>
<P>
After running a script which imports symbols, all of them
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 86812 0.0 0.0 2832 1436 - A 17:59:52 0:00 httpd
httpd 99104 0.0 1.0 4884 3636 - A 17:59:52 0:00 httpd
</PRE>
<P>
Observation: child httpd has grown up by 1868K. Why? Isn't
CGI->compile(':all') supposed to make children to share the compiled
code with parent?
<P>
--------------------------------------------------------------------------------
3. The third script
<P>
<PRE> use strict;
use CGI;
use Data::Dumper;
use Storable;
[and many lines of code, lots of globals - so the code is huge!]
</PRE>
<P>
<Server restarted>
<P>
Nothing preloaded at startup
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 90962 0.0 0.0 1060 1524 - A 17:16:45 0:00 httpd
httpd 86870 0.0 0.0 1304 1784 - A 17:16:45 0:00 httpd
</PRE>
<P>
Script using CGI (methods), Storable, Data::Dumper called
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 90962 0.0 0.0 1064 1436 - A 17:16:45 0:00 httpd
httpd 86870 0.0 1.0 4024 4548 - A 17:16:45 0:00 httpd
</PRE>
<P>
Observation: child httpd has grown up by 2764K
<P>
<Server restarted>
<P>
Preloaded CGI (compiled), Storable, Data::Dumper at startup
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 26792 0.0 0.0 3120 1528 - A 17:19:21 0:00 httpd
httpd 91052 0.0 0.0 3340 1764 - A 17:19:21 0:00 httpd
</PRE>
<P>
Script using CGI (methods), Storable, Data::Dumper called
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 26792 0.0 0.0 3124 1440 - A 17:19:21 0:00 httpd
httpd 91052 0.0 1.0 6568 5040 - A 17:19:21 0:00 httpd
</PRE>
<P>
Observation: child httpd has grown up by 3276K. Great different: 512K
less!!!
<P>
<Server restarted>
<P>
All the above modules + the above script PreCompiled with
Apache::RegistryLoader at startup
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 43224 0.0 0.0 3256 1528 - A 17:23:12 0:00 httpd
httpd 26844 0.0 0.0 3488 1776 - A 17:23:12 0:00 httpd
</PRE>
<P>
Script using CGI (methods), Storable, Data::Dumper called
<P>
<PRE> USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
root 43224 0.0 0.0 3252 1440 - A 17:23:12 0:00 httpd
httpd 26844 0.0 1.0 6748 5092 - A 17:23:12 0:00 httpd
</PRE>
<P>
Observation: child httpd has grown even more 3316K ! Doesn't seem to be
good!
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Profiling">Profiling</A></H1></CENTER>
<P>
Profiling will help you to determine which subroutines are using the most
time and which subroutines are being called most often, then you will
probably will want to optimize those, if your code is a way heavy.
<P>
It is possible to profile code run under mod_perl with the Devel::DProf
module available on CPAN. However, you must have apache version 1.3b3 or
higher and the PerlChildExitHandler enabled. When the server is started,
Devel::DProf installs an END block to write the tmon.out file, which will
be run when the server is shutdown. Here's how to start and stop a server
with the profiler enabled:
<P>
% setenv PERL5OPT -d:DProf % httpd -X -d `pwd` & ... make some requests
to the server here ... % kill `cat logs/httpd.pid` % unsetenv PERL5OPT %
dprofpp
<P>
The Devel::DProf package is a Perl code profiler. This will collect
information on the execution time of a Perl script and of the subs in that
script. This information can be used to determine which subroutines are
using the most time and which subroutines are being called most often. <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/27/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/porting.html
Index: porting.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Writing Mod Perl scripts and Porting plain CGIs to it</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Writing Mod Perl scripts and Porting plain CGIs to it</H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Document_Coverage">Document Coverage</A>
<LI><A HREF="#Before_you_start_to_code">Before you start to code</A>
<LI><A HREF="#Coding_with_mod_perl">Coding with mod_perl</A>
<UL>
<LI><A HREF="#What_s_different_about_modperl">What's different about modperl</A>
<UL>
<LI><A HREF="#Script_s_namespace">Script's namespace</A>
<LI><A HREF="#Names_collisions_with_Modules_an">Names collisions with Modules and libs</A>
<LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
<LI><A HREF="#Output_from_system_calls">Output from system calls</A>
<LI><A HREF="#using_exit_">using exit()</A>
<LI><A HREF="#Running_from_shell">Running from shell</A>
<LI><A HREF="#I_O_is_different">I/O is different</A>
<LI><A HREF="#HTTP_MIME_Headers">HTTP (MIME) Headers</A>
<LI><A HREF="#NPH_SCRIPTS">NPH SCRIPTS </A>
<LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
<LI><A HREF="#END_blocks">END blocks </A>
<LI><A HREF="#Switches_w_T">Switches -w, -T </A>
</UL>
<LI><A HREF="#strict_pragma">strict pragma</A>
<LI><A HREF="#Turning_warnings_ON">Turning warnings ON</A>
<LI><A HREF="#Global_Variables">Global Variables</A>
<LI><A HREF="#Code_is_changed_but_script_seem">Code is changed, but script seems to do the same </A>
<LI><A HREF="#Memory_leakages">Memory leakages</A>
<LI><A HREF="#Sometimes_it_works_Sometimes_Not">Sometimes it works Sometimes Not (Very important!)</A>
<LI><A HREF="#The_Script_is_too_dirty_It_does_">The Script is too dirty,It does the job and I can't afford rewriting it.</A>
</UL>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Document_Coverage">Document Coverage</A></H1></CENTER>
<P>
This document is relevant for both - writing a new cgi from scratch and
migrating from the plain cgi to mod_perl.
<P>
If you are in the porting stage use it as a reference for possible problems
you might encounter when running the existant CGI in the new mode.
<P>
If you are about to write a new cgi from scratch, it would be a good idea
to learn most of the possible pitfalls and to aboid them in first place.
<P>
It covers also the case when the script is too dirty, but does the job and
I can't afford rewriting it. (Apache::PerlRun)
<P>
If your project in hurry, I would think of the following steps: First run
all the scripts in the Apache::PerlRun mode - then as time allows you, move
them into Apache::Registry mode.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Before_you_start_to_code">Before you start to code</A></H1></CENTER>
<P>
It can be a good idea to strength some of the programming skills, since
Apache::Registry doesn't allow sloppiness programming.
<P>
You might want to read:
<UL>
<P><LI><STRONG><A NAME="item_Perl">Perl Module Mechanics</A></STRONG>
<P>
This page describes the mechanics of creating, compiling, releasing and
maintaining Perl modules.
(http://world.std.com/~swmcd/steven/perl/module_mechanics.html)
<P><LI><STRONG><A NAME="item_Mod">Mod Perl Book</A></STRONG>
<P>
(when it will be released) - you can find parts of the book online at <A
HREF="http://www.modperl.com.">http://www.modperl.com.</A>
</UL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Coding_with_mod_perl">Coding with mod_perl</A></H1></CENTER>
<P>
First, before you start coding for Apache::Registry you have to change the
state of your mind. Scripts running under mod_perl are like subroutines are
being called from the daemon who runs all the time. Imagine the daemon
process that when requested to process some of the scripts - reads it in,
compiles it as a subroutine and finally executes it. On any consequent
request it'll just recall the already compiled subroutine. Hope that you
get the idea.
<P>
The best thing you do when coding from scratch is to make it clean and use
packages, as you go thru the notes you will understand why.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="What_s_different_about_modperl">What's different about modperl</A></H2></CENTER>
<P>
There are a few things that behaves differently under mod_perl. It's good
to know what they are.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="Script_s_namespace">Script's namespace</A></H3></CENTER>
<P>
Scripts under Apache::Registry don't not run in package <STRONG>main</STRONG>, they run in a unique namespace based on the requested uri. e.g if your
uri is /perl/test.pl the package will be called
Apache::ROOT::perl::test_2epl;
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="Names_collisions_with_Modules_an">Names collisions with Modules and libs</A></H3></CENTER>
<P>
Just to make things clear before we go into details: each server process
has its own <CODE>%INC</CODE> array which is used to store the information
about compiled modules. Where the keys are the names of the modules or
parameters passed to <CODE>require().</CODE> And values are the real pathes
to these modules. So if you do (assume it's in the <CODE>@INC</CODE> path)
<P>
<PRE> require "./my/lib.pl";
</PRE>
<P>
where <CODE>./my/lib.pl</CODE> is actually a <CODE>/home/httpd/perl/my/lib.pl</CODE>. The following entry will show up in the <CODE>%INC</CODE>
<P>
<PRE> $INC{"./my/lib.pl"} = "/home/httpd/perl/my/lib.pl";
</PRE>
<P>
I'm talking about single server child below!
<P>
You can't have 2 identical module names running under the same server! Only
the first one <CODE>use()d</CODE> or <CODE>require()d</CODE> will be
compiled into the package, the request to the other identical module will
be skipped since server will think that it's already compiled. It'll be
already in child's %INC. (See <A HREF="././status.html#Watching_the_server">Watching the server</A>
section to find out how you can know what is loaded and where)
<P>
So if you have
<P>
<PRE> cgi/tool1/Foo.pm
cgi/tool1/tool1.pl
cgi/tool2/Foo.pm
cgi/tool2/tool2.pl
</PRE>
<P>
And both scripts do: <CODE>use Foo;</CODE> only the first one called will know about Foo, when you will call the
second script it will not know about Foo at all - it's like you've
forgotten to write <CODE>use Foo;</CODE>. Run the server in the <A HREF="././control.html#Single_Mode_Running">single server mode</A> to solve that kind of bugs immediately.
<P>
You will see the following in the error_log file:
<P>
<PRE> Undefined subroutine
&Apache::ROOT::perl::test_2epl::some_function called at
/home/httpd/perl/test.pl line 10.
</PRE>
<P>
The above is true for the files you require as well (assuming that the
required files do not declare a package). If you have:
<P>
<PRE> cgi/tool1/config.pl
cgi/tool1/tool1.pl
cgi/tool2/config.pl
cgi/tool2/tool2.pl
</PRE>
<P>
And both scripts do:
<P>
<PRE> use lib qw(.);
require "config.pl";
</PRE>
<P>
Only the first one will do the require, all for the same reason that
<CODE>%INC</CODE> already includes the key ``config.pl''!
<P>
There are 3 workarounds for that: (make sure you read the whole item 3)
<OL>
<P><LI>
<P>
Add some special path so the fs layout will be something like
<P>
<PRE> cgi/tool1/Tool1/Foo.pm
cgi/tool1/tool1.pl
cgi/tool2/Tool2/Foo.pm
cgi/tool2/tool2.pl
</PRE>
<P>
And you change the scripts:
<P>
<PRE> use Tool1::Foo;
use Tool2::Foo;
</PRE>
<P>
and respectively the package declaration in the modules:
<P>
<PRE> package Tool1::Foo;
package Tool2::Foo;
</PRE>
<P>
For require:
<P>
<PRE> cgi/tool1/tool1-lib/config.pl
cgi/tool1/tool1.pl
cgi/tool2/tool2-lib/config.pl
cgi/tool2/tool2.pl
</PRE>
<P>
And each script does respectively:
<P>
<PRE> use lib qw(.);
require "tool1-lib/config.pl";
</PRE>
<P>
<PRE> use lib qw(.);
require "tool2-lib/config.pl";
</PRE>
<P><LI>
<P>
Or use a full path to the script, so it'll be compiled into the name of the
key in the %INC;
<P>
<PRE> require "/full/path/to/the/config.pl";
</PRE>
<P>
But than you loose portability! (I mean if you move the tool around in the
filesystem you will have to change the base dir)
<P><LI>
<P>
Declare a package in the required files! (Ofcourse it should be unique to
the rest of the package names you use!) The <CODE>%INC</CODE> will use the
package name for the key!
<P>
But then you will have to use Package::function() method unless you will
export the symbols from the <CODE>use()d</CODE> package like
<P>
<PRE> use Package qw(:all_subs);
</PRE>
<P>
This is a bad approach since it'll consume more memory for the current
process.
<P>
<STRONG>Important:</STRONG> Only this solution will work, if you have 2 scripts that
<CODE>require()</CODE> the same file!
<P>
<PRE> cgi/tool1/config.pl
cgi/tool1/tool_1.pl
cgi/tool1/tool_2.pl
</PRE>
<P>
and both tool_1.pl and tool_2.pl do:
<P>
<PRE> use lib qw(.);
require "config.pl";
</PRE>
<P>
Here playing with dir name or using the full path will not help! You must
declare a package inside the files that are being <CODE>require()d!</CODE>
</OL>
<P>
Read also perlmodlib and perlmod manpages.
<P>
From the above discussion it should be clear that you can't run a
development and a production versions of the tools on the same server! You
have to run a separate server for each.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H3></CENTER>
<P>
Apache::Registry scripts cannot contain __END__ or __DATA__ tokens
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="Output_from_system_calls">Output from system calls</A></H3></CENTER>
<P>
Output of system, exec and open PIPE, ``|program'' calls will not be sent
to the browser unless you Perl was configured with sfio.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="using_exit_">using exit()</A></H3></CENTER>
<P>
Perl's <CODE>exit()</CODE> built-in function cannot be used in mod_perl
scripts. Unless you want the server child to exit (which makes the whole
idea of using mod_perl irrelevant). The Apache::exit() function should be
used instead. Apache::exit() automatically overrides the built-in
<CODE>exit()</CODE> for Apache::Registry scripts.
<P>
You might start you scripts with overriding the exit sub (if you use
directly the Apache::exit() you will have the problem to test the script
from the shell, unless you stuff <CODE>use Apache ();</CODE> into your code. I use the following code:
<P>
<PRE> BEGIN {
# Auto-detect if we are running under mod_perl or CGI.
$USE_MOD_PERL = ( (exists $ENV{'GATEWAY_INTERFACE'} and $ENV{'GATEWAY_INTERFACE'} =~ /CGI-Perl/)
or exists $ENV{'MOD_PERL'} ) ? 1 : 0;
}
use subs (exit);
</PRE>
<P>
<PRE> # Select the correct exit way
########
sub exit{
# Apache::exit(-2) will cause the server to exit gracefully,
# once logging happens and protocol, etc (-2 == Apache::Constants::DONE)
$USE_MOD_PERL ? Apache::exit(0) : CORE::exit(0);
}
</PRE>
<P>
Now every time the select will be called the correct exit will be picked,
no matter if you run the script as cgi or from shell.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="Running_from_shell">Running from shell</A></H3></CENTER>
<P>
Your scripts <CODE>*will</CODE> not* run from the command line (yet) unless
you use CGI::Switch or CGI.pm and 5.004+ and do not make any direct calls
to Apache->methods. Since it's different environment and See also above.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="I_O_is_different">I/O is different</A></H3></CENTER>
<P>
If you are using Perl 5.004 most CGI scripts can run under mod_perl
untouched. If you're using 5.003, Perl's built-in <CODE>read()</CODE> and
<CODE>print()</CODE> functions do not work as they do under CGI. If you're
using CGI.pm, use $query->print instead of plain 'ol
<CODE>print().</CODE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="HTTP_MIME_Headers">HTTP (MIME) Headers</A></H3></CENTER>
<P>
By default, mod_perl does not send any headers by itself, however, you may
wish to change this (in httpd.conf):
<P>
<PRE> PerlSendHeader On
</PRE>
<P>
Now the response line and common headers will be sent as they are by
mod_cgi. And, just as with mod_cgi, PerlSendHeader will not send a
terminating newline, your script must send that itself, e.g.:
<P>
<PRE> print "Content-type: text/html\n\n";
</PRE>
<P>
If you're using CGI.pm or CGI::Switch and 'print $q->header' you do
_not_ need PerlSendHeader On.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="NPH_SCRIPTS">NPH SCRIPTS</A></H3></CENTER>
<P>
To run a CGI `nph' script under mod_perl, simply add to your code:
<P>
<PRE> local $| = 1;
</PRE>
<P>
If you normally set PerlSendHeader On, add this to your httpd.conf:
<P>
<PRE> <Files */nph-*>
PerlSendHeader Off
</Files>
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="BEGIN_blocks">BEGIN blocks</A></H3></CENTER>
<P>
Perl executes BEGIN blocks during the compile time of code as soon as
possible. The same is true under mod_perl. However, since mod_perl normally
only compiles scripts and modules once, in the parent server or once
per-child, BEGIN blocks in that code will only be run once. As perlmod
explains, once a BEGIN has run, it is immediately undefined. In the
mod_perl environment, this means BEGIN blocks will not be run during each
incoming request unless that request happens to be one that is compiling
the code.
<P>
Modules and files pulled in via require/use which contain BEGIN blocks will
be executed: - only once, if pulled in by the parent process - once
per-child process if not pulled in by the parent process - an additional
time, once per-child process if the module is pulled in off of disk again
via Apache::StatINC - an additional time, in the parent process on each
restart if PerlFreshRestart is On - unpredictable if you fiddle with
<CODE>%INC</CODE> yourself
<P>
Apache::Registry scripts which contain BEGIN blocks will be executed: -
only once, if pulled in by the parent process via Apache::RegistryLoader -
once per-child process if not pulled in by the parent process - an
additional time, once per-child process if the script file has changed on
disk - an additional time, in the parent process on each restart if pulled
in by the parent process via Apache::RegistryLoader and PerlFreshRestart is
On
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="END_blocks">END blocks</A></H3></CENTER>
<P>
As perlmod explains, an END subroutine is executed as late as possible,
that is, when the interpreter is being exited. In the mod_perl environment,
the interpreter does not exit until the server is shutdown. However,
mod_perl does make a special case for Apache::Registry scripts.
<P>
Normally, END blocks are executed by Perl during it's
<CODE>perl_run()</CODE> function, which is called once each time the Perl
program is executed, e.g. once per (mod_cgi) CGI scripts. However, mod_perl
only calls <CODE>perl_run()</CODE> once, during server startup. Any END
blocks encountered during main server startup, i.e. those pulled in by the
PerlRequire or by any PerlModule are suspended and run at server shutdown,
aka child_exit (requires apache 1.3b3+). Any END blocks that are
encountered during compilation of Apache::Registry scripts are called after
the script done is running, including subsequent invocations when the
script is cached in memory. All other END blocks encountered during other
Perl*Handler callbacks, e.g. PerlChildInitHandler, will be suspended while
the process is running and called during child_exit when the process is
shutting down. Module authors may be wish to use $r->register_cleanup as
an alternative to END blocks if this behavior is not desirable.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H3><A NAME="Switches_w_T">Switches -w, -T</A></H3></CENTER>
<P>
Normally when you run perl from the command line or have the shell invoke
it with `#!', you may choose to pass perl switch arguments such as -w or
-T. Since the command line is only parsed once, when the server starts,
these switches are unavailable to mod_perl scripts. However, most command
line arguments have a perl special variable equivilant. For example, the
$^W variable coresponds to the -w switch. Consult perlvar for more details.
With mod_perl it is also possible to turn on warnings globaly via the
PerlWarn directive:
<P>
<PRE> PerlWarn On
</PRE>
<P>
You can turn it off with <CODE>local $^W = 0;</CODE> in your scripts on the local basis (or inside the block).
<P>
The switch which enables taint checks does not have a special variable, so
mod_perl provides the PerlTaintCheck directive to turn on taint checks. In
httpd.conf, enable with:
<P>
<PRE> PerlTaintCheck On
</PRE>
<P>
Now, any and all code compiled inside httpd will be checked.
<P>
The environment variable PERL5OPT can be used to set additional perl
startup flags such as -d and -D. See perlrun.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="strict_pragma">strict pragma</A></H2></CENTER>
<P>
It's absolutely mandatory to start all your scripts with:
<P>
<PRE> use strict; (at least for development)
</PRE>
<P>
If you need you can always to turn off the 'strict' pragma inside the
block, e.g:
<P>
<PRE> {
no strict 'refs';
... some code
}
</PRE>
<P>
It's more important to have use strict enabled under mod_perl Perl than
anywhere else, while it's not required, it strongly recommended, it will
save you more time in the long run. And, of course, clean scripts will
still run under mod_cgi (plain CGI)!
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Turning_warnings_ON">Turning warnings ON</A></H2></CENTER>
<P>
Have a <CODE>$^W=1</CODE> in the script or PerlWarn ON at the server config file. Turning the warning
on will save you a lot of troubles with debugging your code. Note that
first magic line <CODE>#!/perl -swithces</CODE>
#is ignored by mod_perl so do the switches you used to write there.
<P>
If you need you can always turn off the warning with <CODE>$^W = 0</CODE> in your code, if you have some section you don't want the perl compiler to
warn in.
<P>
In a production code it can be a good idea to have the Warnings Off.
Otherwise if your code isn't very clean and spits a few lines of warns here
and there, you will end up with a huge error_log file in a short time on
the loaded server.
<P>
<CODE>use diagnostics;</CODE> can put more light on the errors and warns you see, But you better don't
use <CODE>use diagnostics;</CODE>
in the production, since you end up in a huge overhead of the diagnostics
pragma. (run the script with -dDprof to check the overhead. See
Devel::Dprof for more info)
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Global_Variables">Global Variables</A></H2></CENTER>
<P>
It's always a good idea to stay away from global variables when possible.
Some variables must be global so Perl can see them, such as a module's
<CODE>@ISA</CODE> or <CODE>$VERSION</CODE> variables. In common practice, a
combination of use strict and use vars keeps modules clean and reduces a
bit of noise. However, use vars also creates aliases as the Exporter does,
which eat up more space. When possible, try to use fully qualified names
instead of use vars. Example:
<P>
<PRE> package MyPackage;
use strict;
@MyPackage::ISA = qw(...);
$MyPackage::VERSION = "1.00";
</PRE>
<P>
<PRE> vs.
</PRE>
<P>
<PRE> package MyPackage;
use strict;
use vars qw(@ISA $VERSION);
@ISA = qw(...);
$VERSION = "1.00";
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Code_is_changed_but_script_seem">Code is changed, but script seems to do the same</A></H2></CENTER>
<P>
Files pulled in via use or require statements are not automatically
reloaded when changed on disk. See <A HREF="././obvious.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A> for more info.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Memory_leakages">Memory leakages</A></H2></CENTER>
<P>
Scripts under mod_perl can very easily leak memory! Global variables stay
around indefinitely, lexical variables (declared with <Cmy()> are
destroyed when they go out of scope, provided there are no references to
them from outside of that scope.
<P>
Perl doesn't return back the memory it acquired from the kernel. It does
reuse it so!
<P>
<STRONG>First example</STRONG> is file reading:
<P>
<PRE> open IN, $file or die $!;
$/ = undef; # will read the whole file in
$content = <IN>;
close IN;
</PRE>
<P>
If you file is of a 5Mb - The child who served that script will grow
exectly by that size. Now if you have 20 childs and all of them will serve
this cgi, all of them will consume additional 20*5M = 100M of RAM! If
that's the case try to use other approaches of processing the file, if
possible ofcourse. Try to process line at a time and print it back to the
file (if you need to modify the file itself, use temperary file for that,
when finished overwrite the src file, make sure to provide locking
mechanism!)
<P>
<STRONG>Second example</STRONG> is copying variables between functions (passing variables by value). Let's
use the example above. Assuming we have no choice and the whole file had to
be read before any data processing. Now you have a very nice sub
<CODE>process()</CODE> that processes the data and returns it back. What
happens if you pass the <CODE>$content</CODE> by value? You have just
copied another 5M and the child growed up by another 5M in size (watch your
swap space!) now multiply it again by factor of 10 you have 200M of wasted
RAM, which will be apparently reused but it's a waste! Whenever you think
the variable can grow bigger than few Kb pass it by reference! Once I wrote
the script that passed a content of the little DB to the function and it
was OK, but then the DB become huge - I had to make a decision, whether to
buy more memory or to rewrite the code. So it's better to plan ahead and
pass the variables by reference. There are few approaches for that:
<P>
<PRE> sub process{
my $content_r = shift;
... some processing on $$content here ($$var_r - dereference the scalar)
[nothing returned - the variable $content outside is already changed
}
process(\$content);
</PRE>
<P>
@{$var_lr} - dereference an array %{$var_hr} = dereference a hash
<P>
For more see <CODE>perldoc perlref</CODE>
<P>
Other approach would be to use directly the <CODE>@_</CODE> variable. Using
directly the <CODE>@_</CODE> array serves the job of passing by reference!
<P>
<PRE> sub process{
$_[0] =~ s/A/a/gs;
... some processing on $_[0] here
[nothing returned - the variable $content outside is already changed
}
process($content);
</PRE>
<P>
From <CODE>perldoc perlsub</CODE>: The array <CODE>@_</CODE> is a local array, but its elements are aliases
for the actual scalar parameters. In particular, if an element $_[0] is
updated, the corresponding argument is updated (or an error occurs if it is
not updatable)....
<P>
<STRONG>Third example</STRONG> is work with DataBases. If you do some DB processing, many times you have
lots of records that you read into you program, and then print them to the
browser after they were formatted. (I even don't mention the horrible case
where programmers read in the whole DB and then let the perl to process
it!!! Use relational DB and let the SQL do the job, so you get only the
records you need!!!)
<P>
We will use DBI for that (assume we are already connected to the DB) (read
perldoc DBI for complete info):
<P>
<PRE> $sth->execute;
while(@row_ary = $sth->fetchrow_array;) {
<do DB accumulation into some variable>
}
<print the output using the the data returned from the DB>
</PRE>
<P>
In the example above the httpd_process will grow up by the size of the
variables that have been alocated for the records that matched the query.
(Again remember to multiply it by the number of the childs server runs!)
<P>
What you want to do is to not accumulate the records but print them as they
are fetched from the DB. More over we use a bind_col and
$sth->fetchrow_arrayref (aliased to $sth->fetch) methods, to get the
the fastest way to fetch data. The example below prints the TABLE with
matched data, the only memory that is being used is a <CODE>@cols</CODE>
<P>
<PRE> my @select_fields = qw(a b c);
# create a list of cols values
my @cols = ();
@cols[0..$#select_fields] = ();
$sth = $dbh->prepare($do_sql);
$sth->execute;
# Bind perl variables to columns.
$sth->bind_columns(undef,\(@cols));
print "<TABLE>";
while($sth->fetch) {
print "<TR>";
print map { "<TD>$_</TD>" } @cols;
print "</TR>";
}
print "</TABLE>";
</PRE>
<P>
Note: the above method doesn't allow you to know how many records has been
matched. The workaround is to run an identical query before the code above
where you use 'SELECT <CODE>count(*)</CODE> ...' instead of 'SELECT * ...',
so you get the number of matched records.
<P>
Just as a bonus, I wanted to write a single sub that process any query but
very flexible, since it accepts: conditions,callback closure sub, select
fields and restrictions.
<P>
<PRE> # $o->dump(\%conditions,\&callback_closure,\@select_fields,@restrictions)
sub dump{
my $self = shift;
my %param = %{+shift}; # dereference hash
my $rsub = shift;
my @select_fields = @{+shift}; # dereference list
my @restrict = shift || '';
# create a list of cols values
my @cols = ();
@cols[0..$#select_fields] = ();
my $do_sql = '';
my @where = ();
# make a @where list
map { push @where, "$_=\'$param{$_}\'" if $param{$_};} keys %param;
# prepare the sql statement
$do_sql = "SELECT ";
$do_sql .= join(" ", @restrict) if @restrict;# append the restriction list
$do_sql .= " " .join(",", @select_fields) ; # append the select list
$do_sql .= " FROM $DBConfig{TABLE} "; # from table
</PRE>
<P>
<PRE> # we will not add the WHERE clause if @where is empty
$do_sql .= " WHERE " . join " AND ", @where if @where;
print "SQL: $do_sql \n" if $debug;
$dbh->{RaiseError} = 1; # do this, or check every call for errors
$sth = $dbh->prepare($do_sql);
$sth->execute;
# Bind perl variables to columns.
$sth->bind_columns(undef,\(@cols));
while($sth->fetch) {
&$rsub(@cols);
}
# print the tail or "no records found" message according to the previous calls
&$rsub();
} # end of sub dump
</PRE>
<P>
Now a callback closure sub can do lots of things. We need a closure to know
what stage are we in: header, body ot tail. For example a callback closure
for formatting the rows we want to print:
<P>
<PRE> my $rsub = eval {
# make a copy of @fields list, since it might go out of scope when this closure will be called
my @fields = @fields;
my @query_fields = qw(user dir tool act); # no date field!!!
my $header = 0;
my $tail = 0;
my $counter = 0;
my %cols = (); # columns name=> value hash
# Closure with the following behaviour:
# 1. Header's code will be executed on the first call only and if @_ was set
# 2. Row's printing code will be executed on every call with @_ set
# 3. Tail's code will be executed only if Header's code was printed and @_ isn't set
# 4. "No record found" code will be executed if Header's code wasn't executed
sub {
# Header
if (@_ and !$header){
print "<TABLE>\n";
print $q->Tr(map{ $q->td($_) } @fields );
$header = 1;
}
# Body
if (@_) {
print $q->Tr(map{$q->td($_)} @_ );
$counter++;
return;
}
# Tail, will be printed only at the end
if ($header and !($tail or @_)){
print "</TABLE>\n $counter records found";
$tail = 1;
return;
}
# No record found
unless ($header){
print $q->p($q->center($q->b("No record was found!\n")));
}
</PRE>
<P>
<PRE> } # end of sub {}
}; # end of my $rsub = eval {
</PRE>
<P>
You might want to check also <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>
and <A HREF="././performance.html#Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Sometimes_it_works_Sometimes_Not">Sometimes it works Sometimes Not (Very important!)</A></H2></CENTER>
<P>
When you start running the scripts under mod_perl you might find yourself
in situation that scripts seems to work, but sometimes it screws up. And
the more it runs without restart the more it screws up. Many times you can
resolve this problem very easily. You have to test your script under with
Server running as a
<A HREF="././control.html#Single_Mode_Running">single process</A>
<P>
Generally the problem you have is using global variables. Since global
variables don't change from one script envocation to another unless you
change it, you can find your scripts do ``fancy'' things.
<P>
The first example is amazing. Web Services. Imagine that you enter some
site you have your account on (Free Email Account?). Now you want to see
what other users read
<P>
You type in your name and passwd, and you are expecting to enter to your
account, but instead to enter the account of someone else. This is cool
isn't it? Is it a bug or feature. (For some of us it's a feature, while for
others it's a bug :( You say, why in the world this happens? The answer is
simple: Global Variables. You have entered the account of someone who
happened to be served by the same server child as you, because of the
sloppiness programming, the global variable was not reset at the beginning
of the program and voula you can easily peek into other people emails! You
would ask it can't happen, since you have entered the login and passwd. I
tell you, it happens! See for yourself:
<P>
<PRE> use vars ($authenticated);
my $q = new CGI;
my $username = $q->param('username');
my $passwd = $q->param('passwd');
authenticate($username,$passwd);
# failed, break out
die "Wrong passwd" unless $authenticated == 1;
# user is Ok, fetch user's data
show_user($username);
</PRE>
<P>
<PRE> sub authenticate{
my ($username,$passwd) = @_;
# some checking
$authenticated = 1 if (SOMETHING);
}
</PRE>
<P>
Do you see the catch? I can type in any valid username and any dummy passwd
and enter that's user account, with the code above if someone has
sucessfully entered his account before me using the same child process!
Since <CODE>$authenticated</CODE> is global - if it becomes 1 once it'll be
1 for the whole child's life!!! The solution is trivial - reset the
<CODE>$authenticated</CODE> to 0 at the beginning of the program. (Or many
other different solution). Ofcourse the example is too trivial - but
beleive me it happens!
<P>
Just another little one linner that can make your day spoiled, assuming you
forgot to reset the $allowed. It's perfectly OK in plain mod_cgi :
<P>
<PRE> $allowed = 1 if $username eq 'admin'; #
</PRE>
<P>
But you will let any user to admin your system with the line above (again
assuming you have used the same child prior to some user request)
<P>
Another good example is usage of /o in regexp. After you restart the server
most likely you will not detect the problem, if on every request you will
use a different pattern that will be used in regex and it'll happen that
each time a different child will serve the new request. Only arriving to
the child who has already cached the regex will reveal the problem, but
generally you miss that and when you press reload - You see that it works
(new fresh child) and then it doesn't (child that already cached the regex
and wouldn't recompile because of /o).
<P>
So to make sure you don't miss these bugs always test your CGI in
<A HREF="././control.html#Single_Mode_Running">single process</A>. To solve this particular <STRONG>/o</STRONG> problem refer to <A HREF="././obvious.html#Regular_Expressions">Regular Expressions</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="The_Script_is_too_dirty_It_does_">The Script is too dirty,It does the job and I can't afford rewriting it.</A></H2></CENTER>
<P>
You still can win from using mod_perl.
<P>
One approach it to replace the Apache::Registry handler with
Apache::PerlRun and defined a new location (the script can reside in the
same directory on the disk.
<P>
<PRE> # srm.conf
ScriptAlias /cgi-perl/ /home/httpd/cgi/
# httpd.conf
<Location /cgi-perl>
#AllowOverride None
SetHandler perl-script
PerlHandler Apache::PerlRun
Options ExecCGI
allow from all
PerlSendHeader On
</Location>
Apache::PerlRun gives you a
benefit of preloaded perl and its modules. This module's handler emulates
the CGI environment, allowing programmers to write scripts that run
under CGI or mod_perl without change. Unlike Apache::Registry, the
Apache::PerlRun handler does not cache the script inside of a
subroutine. Scripts will be "compiled" every request. After the
script has run, it's namespace is flushed of all variables and
subroutines. Still, you don't have the overhead of perl and its
modules load and compilation time! (If your script is light, but uses
lots of standard modules - you will almost not see the difference
between Apache::PerlRun and Apache::Registry !).
</PRE>
<P>
Be aware though, that if you use some packages that use internals variables
that has circular references, they will be not flushed!!!
<P>
META: Complete the above
<P>
Another bad, but working method is to set MaxRequestsPerChild to 1, which
will force each child to exit after server one request, so you'll get the
preloaded modules, etc., the script will be compiled each request, then
killed off. This isn't good for ``high-traffic'' sites though, as the
parent server will need to fork a new child each time one is killed, but
you can fiddle with MaxStartServers, MinSpareServers, to make the parent to
spawn more servers ahead so the killed one will be immediately replaced
with the fresh ones. Again, probably that's not what you want.
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/27/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/scenario.html
Index: scenario.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Real World scenario</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Real World scenario</H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Making_a_strategic_decision">Making a strategic decision</A>
<LI><A HREF="#Deciding_on_directories_layout">Deciding on directories layout</A>
<LI><A HREF="#Configuration_and_compilation_of">Configuration and compilation of the sources. </A>
<UL>
<LI><A HREF="#httpd_docs_server">httpd_docs server</A>
<LI><A HREF="#httpd_perl_server_mod_perl_">httpd_perl server (mod_perl):</A>
</UL>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Making_a_strategic_decision">Making a strategic decision</A></H1></CENTER>
<P>
When you will run your scripts under mod_perl - you will notice that the
httpd processes consumes a huge pieces of memory, from 5M to 25M and more.
Since there is no free dinner, that's the price we pay for the great speed
improvements under mod_perl. But it doesn't mean that you should serve the
static objects like images and html docs with these processes. It's an
overkill. The best approach is to run 2 servers: a light apache server with
no mod_perl compiled in to serve the static pages, and a heavy
apache/mod_perl server to server the cgis in mod_perl mode only. This
section describes a real world example ready for copy and paste to start
with. You will probably will want to change the base directories, but
basically you can pick it as it is.
<P>
Since we run 2 apache servers we will need 2 different configuration files,
log files and etc. We need a special directory layout. While some of the
directories can be shared between 2 servers (assuming that use the same
source distribution for both servers, other should be separated. I choose
to make the difference between 2 servers by calling them httpd_docs
(apache) and httpd_perl (apache/mod_perl).
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Deciding_on_directories_layout">Deciding on directories layout</A></H1></CENTER>
<P>
We will make /usr/apps our <STRONG>root</STRONG> directory. We will build all the dir tree there. (/usr/apps/bin
/usr/apps/etc and etc...)
<P>
First let's prepare the sources. We assume that all the sources go to
/usr/apps/usr/src dir. First lets make 2 subdirs:
<P>
<PRE> % mkdir /usr/apps/usr/src/httpd_docs
% mkdir /usr/apps/usr/src/httpd_perl
</PRE>
<P>
Now we put the apache source into /usr/apps/usr/src/httpd_docs:
<P>
<PRE> % cd /usr/apps/usr/src/httpd_docs
% cp ~/apache.tar.gz .
% gzip -d apache.tar.gz
% tar xvf apache.tar
</PRE>
<P>
let's check:
<P>
<PRE> % ls -l
drwxr-xr-x 8 stas stas 2048 Oct 29 17:38 apache_1.3.2/
</PRE>
<P>
Prepare the httpd_perl server sources
<P>
<PRE> % cd /usr/apps/usr/src/httpd_perl
% cp ~/apache.tar.gz .
% gzip -d apache.tar.gz
% tar xvf apache.tar
% cp ~/modperl.tar.gz .
% gzip -d modperl.tar.gz
% tar xvf modperl.tar
</PRE>
<P>
let's check
<P>
<PRE> % ls -l
drwxr-xr-x 8 stas stas 2048 Oct 29 17:38 apache_1.3.2/
drwxr-xr-x 8 stas stas 2048 Oct 29 17:38 modperl-1.16/
</PRE>
<P>
Time to decide the desired directories structure layout (Where apache files
go):
<P>
<PRE> ROOT = /usr/apps
</PRE>
<P>
Both Servers Can share the following dirs (so we will not duplicate data):
<P>
<PRE> /usr/apps/bin/
/usr/apps/lib
/usr/apps/include/
/usr/apps/man/
/usr/apps/share/
</PRE>
<P>
<STRONG>Important:</STRONG> we assume that both servers comes from the same source
<P>
Servers store their specific files either in httpd_docs or httpd_perl:
<P>
<PRE> /usr/apps/etc/httpd_docs/
httpd_perl/
</PRE>
<P>
<PRE> /usr/apps/sbin/httpd_docs/
httpd_perl/
</PRE>
<P>
<PRE> /usr/apps/var/httpd_docs/logs/
proxy/
run/
httpd_perl/logs/
proxy/
run/
</PRE>
<P>
Next step is to configure and compile the sources: Below are the procedures
to compile both servers taking into account the above directories layout:
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Configuration_and_compilation_of">Configuration and compilation of the sources.</A></H1></CENTER>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="httpd_docs_server">httpd_docs server</A></H2></CENTER>
<DL>
<P><DT><STRONG><A NAME="item_Configuration">Configuration</A></STRONG><DD>
<P>
<PRE> % cd /usr/apps/usr/src/httpd_docs/apache_1.3.2
</PRE>
<P>
<PRE> % make clean
</PRE>
<P>
<PRE> # gcc - compiles httpd by 100K+ smaller on AIX!
</PRE>
<P>
<PRE> % env CC=gcc \
./configure --prefix=/usr/apps \
--sbindir=/usr/apps/sbin/httpd_docs \
--sysconfdir=/usr/apps/etc/httpd_docs \
--localstatedir=/usr/apps/var/httpd_docs \
--runtimedir=/usr/apps/var/httpd_docs/run \
--logfiledir=/usr/apps/var/httpd_docs/logs \
--proxycachedir=/usr/apps/var/httpd_docs/proxy \
--enable-module=include --enable-module=rewrite
</PRE>
<P>
Note: add --layout to see the resulting dirs layout without actually making
the configuration.
<P><DT><STRONG><A NAME="item_Compilation">Compilation:</A></STRONG><DD>
<P>
<PRE> % make
</PRE>
<P>
<PRE> % make install
</PRE>
<P>
Rename the 'httpd' to 'http_docs'
<P>
<PRE> % mv /usr/apps/sbin/httpd_docs/httpd /usr/apps/sbin/httpd_docs/httpd_docs
</PRE>
<P>
Now update the apachectl util to point to a new httpd name (by hand or by
using perl)
<P>
<PRE> % perl -p -i -e 's|httpd_docs/httpd|httpd_docs/httpd_docs|' /usr/apps/sbin/httpd_docs/apachectl
</PRE>
</DL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="httpd_perl_server_mod_perl_">httpd_perl server (mod_perl):</A></H2></CENTER>
<P>
<PRE> % cd /usr/apps/usr/src/httpd_perl/apache_1.3.2
% make clean
% cd /usr/apps/usr/src/httpd_perl/mod_perl-1.16
% make clean
</PRE>
<P>
Here I didn't find a way to compile with gcc (but perl was compiled with cc
so we have to compile with the same compiler!!!
<P>
Note the APACI_ARGS (below) must be passed as one long line!!!
<P>
<PRE> % /usr/apps/bin/perl Makefile.PL \
APACHE_PREFIX=/usr/apps/ \
APACHE_SRC=../apache_1.3.2/src \
DO_HTTPD=1 \
USE_APACI=1 \
PERL_MARK_WHERE=1 \
PERL_STACKED_HANDLERS=1 \
ALL_HOOKS=1 \
APACI_ARGS=--sbindir=/usr/apps/sbin/httpd_perl,--sysconfdir=/usr/apps/etc/httpd_perl,
--localstatedir=/usr/apps/var/httpd_perl,--runtimedir=/usr/apps/var/httpd_perl/run,
--logfiledir=/usr/apps/var/httpd_perl/logs,--proxycachedir=/usr/apps/var/httpd_perl/proxy,
--enable-module=rewrite
</PRE>
<P>
Notes: -DPERL_STACKED_HANDLERS needed for Apache::DBI
<P>
<PRE> % make && make test && make install
</PRE>
<P>
Note: Apache puts a stripped version of httpd at
/usr/apps/sbin/httpd_perl/httpd the original version sits at
/usr/apps/usr/src/httpd_perl/apache_1.3.2/src/httpd
<P>
<PRE>
rename the 'httpd' to 'http_perl'
</PRE>
<P>
<PRE> % mv /usr/apps/sbin/httpd_perl/httpd /usr/apps/sbin/httpd_perl/httpd_perl
</PRE>
<P>
now update the apachectl util to point to a new httpd name (by hand or by
using perl)
<P>
<PRE> % perl -p -i -e 's|httpd_perl/httpd|httpd_perl/httpd_perl|' /usr/apps/sbin/httpd_perl/apachectl
</PRE>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/16/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/snippets.html
Index: snippets.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Code Snippets</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Code Snippets</H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
<LI><A HREF="#Sending_MIME_headers">Sending MIME headers</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A></H1></CENTER>
<P>
To trap all/most Perl run-time errors and send the output to the client
instead of Apache's error log add this line to your script.
<P>
<PRE> use CGI::Carp qw(fatalsToBrowser);
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Sending_MIME_headers">Sending MIME headers</A></H1></CENTER>
<P>
By default, mod_perl does not send any headers by itself, however, you may
wish to change this:
<P>
<PRE> PerlSendHeader On
</PRE>
<P>
The safest bet is to use CGI.pm's <CODE>print $query-</CODE><CODE>header()></CODE> method (If you do you don't need the above
setting)
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/17/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/start.html
Index: start.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Getting Started with mod_perl</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Getting Started with mod_perl</H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Coverage">Coverage </A>
<LI><A HREF="#Downloading_the_needed_component">Downloading the needed components.</A>
<UL>
<LI><A HREF="#Perl">Perl</A>
<LI><A HREF="#Apache">Apache</A>
<LI><A HREF="#Mod_Perl">Mod_Perl</A>
</UL>
<LI><A HREF="#Configuration_and_Installation">Configuration and Installation</A>
<UL>
<LI><A HREF="#Perl">Perl</A>
<LI><A HREF="#Apache">Apache</A>
<LI><A HREF="#Mod_Perl">Mod_Perl</A>
</UL>
<LI><A HREF="#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is really installed</A>
<UL>
<LI><A HREF="#Testing_by_calling_the_perl_sta">Testing by calling the /perl-status </A>
<LI><A HREF="#Testing_by_telneting_to_the_port">Testing by telneting to the port server's listening to</A>
<LI><A HREF="#Run_a_cgi_that_shows_you_your_se">Run a cgi that shows you your server's environment</A>
</UL>
<LI><A HREF="#Starting_to_use_the_server">Starting to use the server</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
<P>
This sections gets you a quick review of configuration and installation of
the required tools. For a kickstart tutorial, whci will allow you make to
make copy and paste slick installation, see
<A HREF="././scenario.html#">Real World Scenario</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Downloading_the_needed_component">Downloading the needed components.</A></H1></CENTER>
<P>
In order to start using the mod_perl - you will need to get first Perl,
Apache webserver and mod_perl itself. Below you will find the needed
information.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Perl">Perl</A></H2></CENTER>
<P>
Probably perl is already installed at your machine. But check the version
you use. You better get the perl5.004 and higher version. You can get the
latest perl version from <A
HREF="http://www.perl.com.">http://www.perl.com.</A> Try the direct
download link <A
HREF="http://www.perl.com/pace/pub/perldocs/latest.html.">http://www.perl.com/pace/pub/perldocs/latest.html.</A>
As of this writing the latest maintain (production) release is perl5.00503.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Apache">Apache</A></H2></CENTER>
<P>
Get the latest apache webserver from <A
HREF="http://www.apache.org.">http://www.apache.org.</A> Try the direct
download link [http://www.apache.org/dist/]. As of this writing the latest
production release is apache-1.3.3.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Mod_Perl">Mod_Perl</A></H2></CENTER>
<P>
Get the latest mod_perl from <A
HREF="http://perl.apache.org.">http://perl.apache.org.</A> Try the direct
download link [http://perl.apache.org/dist/]. As of this writing the latest
production release is mod_perl-1.16_02
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Configuration_and_Installation">Configuration and Installation</A></H1></CENTER>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Perl">Perl</A></H2></CENTER>
<P>
First install perl. Follow the instructions in the distribution's INSTALL
file. During the configuration stage (while running
<CODE>./Configure</CODE>), make sure you answer <CODE>YES</CODE> to:
<P>
<PRE> Do you wish to use dynamic loading? [y]
</PRE>
<P>
You will want this feature on to dynamically load the Perl
Modules/extensions.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Apache">Apache</A></H2></CENTER>
<P>
It will be a good idea to try to install the Apache webserver without
mod_perl first. So later if something going wrong you will know that it's
not apache's server problem. But you can skip this stage. In any case you
have to open the source distribution of apache prefferably at the same
level with modperl distribution.
<P>
<PRE> % ls -l /usr/src
drwxr-xr-x 8 stas bar 2048 Oct 6 09:46 apache_1.3.2/
drwxr-xr-x 19 stas bar 4096 Oct 2 14:33 mod_perl-1.16/
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Mod_Perl">Mod_Perl</A></H2></CENTER>
<P>
Now we come to the main point.
<P>
Here I'll give only a short example of mod_perl installation. You should
read the real world scenario for a more complete description.
<P>
As with any perl package the installation of mod_perl is very easy and
standard. perldoc INSTALL will guide you thru the configuration and
installation process.
<P>
The fastest way to install would be:
<P>
<PRE> % perl Makefile.PL APACHE_SRC=../apache_1.3.2/src \
DO_HTTPD=1 PERL_MARK_WHERE=1 EVERYTHING=1
% make &amp;&amp; make test &amp;&amp; make install
</PRE>
<P>
To change the installation target (either if you aren't root or you need to
install a second copy for testing purposes), assuming you use /foo/server
as a base directory root, you have to run this:
<P>
<PRE> % perl Makefile.PL APACHE_SRC=../apache_1.3.2/src \
DO_HTTPD=1 PERL_MARK_WHERE=1 EVERYTHING=1 \
APACHE_PREFIX=/foo/server PREFIX=/foo/server
</PRE>
<P>
Where <CODE>PREFIX</CODE> says where to install the perl modules,
<CODE>APACHE_PREFIX</CODE> - the same for the apache files.
<P>
Next step is to configure the mod_perl sections in the apache conf files.
See <A HREF="././config.html#">ModPerlConfiguration</A>
<P>
Fire up the server with <CODE>/foo/server/sbin/apachectl start</CODE>, Watch the error log file if server doesn't start up (No error message
will be printed to the console!)
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is really installed</A></H1></CENTER>
<P>
There a few ways. In older versions of apache you could see that by running <CODE>httpd -v</CODE>, it's no longer work!
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Testing_by_calling_the_perl_sta">Testing by calling the /perl-status</A></H2></CENTER>
<P>
Fetch: <A
HREF="http://www.yourserver.com/perl-status">http://www.yourserver.com/perl-status</A>
from your favorite Netscape browser :-) (Assuming you have configured the
<Location /perl-status> Section in the server config file (referer to
<A HREF="././config.html#">ModPerlConfiguration</A>)
<P>
You should see something like this:
<P>
<PRE> Embedded Perl version 5.00502 for Apache/1.3.1 (Unix) mod_perl/1.16
process 50880, running since Tue Oct 6 14:31:45 1998
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Testing_by_telneting_to_the_port">Testing by telneting to the port server's listening to</A></H2></CENTER>
<P>
Assume that you set <CODE>Port 8080</CODE> in the httpd.conf for your mod_perl server. You have to telnet to your
server port 8080, then you should type <CODE>HEAD / HTTP/1.0</CODE> then press the <ENTER> key TWICE!
<P>
<PRE> % telnet yourserver.com 8080<ENTER>
HEAD / HTTP/1.0<ENTER><ENTER>
</PRE>
<P>
You should see a respond like this:
<P>
<PRE> HTTP/1.1 200 OK
Date: Tue, 01 Dec 1998 12:27:52 GMT
Server: Apache/1.3.2 (Unix) mod_perl/1.16_01
Connection: close
Content-Type: text/html
Connection closed.
</PRE>
<P>
So you see <CODE>Server: Apache/1.3.2 (Unix) mod_perl/1.16_01</CODE> - which says that you do have mod_perl installed and it's 1.16_01. Ofcourse
in your case it would be the version you have installed.
<P>
However, just because you've got it linked in there, that doesn't meant
that you have your server configured to use mod_perl to handle Perl
scripts. You will find the configuaration assistance at
<A HREF="././config.html#">ModPerlConfiguration</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Run_a_cgi_that_shows_you_your_se">Run a cgi that shows you your server's environment</A></H2></CENTER>
<P>
Copy and paste the script below (no need for perl line!). Let's say you
called it test.pl, you saved it into the root of the cgi scripts, and cgi
root is mapped directly to /perl of your server.
<P>
<PRE> print "Content-type: text/html\n\n";
print "Server's environment<P>\n";
print "<TABLE>";
foreach ( keys %ENV ) {
print "<TR><TD>$_ </TD><TD>$ENV{$_}</TR></TD>";
}
print "</TABLE>";
</PRE>
<P>
Make it executable:
<P>
<PRE> % chmod a+x test.pl
</PRE>
<P>
Now fetch the <A
HREF="http://www.you.com:8080/perl/test.pl">http://www.you.com:8080/perl/test.pl</A>
. You should see something like this (part of the output was snipped).
<P>
<PRE> SERVER_SOFTWARE Apache/1.3.2 (Unix) mod_perl/1.16_01
GATEWAY_INTERFACE CGI-Perl/1.1
REQUEST_METHOD GET
HTTP_ACCEPT image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
MOD_PERL 1.16_01
REQUEST_URI /perl/test.pl
SCRIPT_NAME /perl/test.pl
[...snipped]
</PRE>
<P>
Now if I run the same script in mod_cgi mode (configured with /cgi-bin)
(you must add the perl line #!/bin/perl for the above script) and fetch <A
HREF="http://www.you.com/cgi-bin/test.pl">http://www.you.com/cgi-bin/test.pl</A>
<P>
<PRE> SERVER_SOFTWARE Apache/1.3.2 (Unix)
GATEWAY_INTERFACE CGI/1.1
[...snipped]
</PRE>
<P>
You will see that 2 environment variables <CODE>SERVER_SOFTWARE</CODE> and
<CODE>GATEWAY_INTERFACE</CODE> are different from the case above. So you've got the hint how to tell in
what mode you are running in your cgi scripts. I start all my cgi scripts
that are mod_perl aware with:
<P>
<PRE> BEGIN {
# Auto-detect if we are running under mod_perl or CGI.
$USE_MOD_PERL = ( (exists $ENV{'GATEWAY_INTERFACE'} and $ENV{'GATEWAY_INTERFACE'} =~ /CGI-Perl/)
or exists $ENV{'MOD_PERL'} ) ? 1 : 0;
# perl5.004 is a must under mod_perl
require 5.004 if $USE_MOD_PERL;
}
</PRE>
<P>
You might wander why in the world you will need to know in what mode you
are running. For example you will want to use <CODE>Apache::exit()</CODE>
and not <CODE>CORE::exit()</CODE> in your scripts, but if you think that your script might be used in both
environments (mod_cgi vs mod_perl), you will have to override the <CODE>exit()</CODE> subroutine and to make the runtime decision of what method you will use.
For reasons and implementations see: <A HREF="././porting.html#using_exit_">Using exit()</A> and the whole <A HREF="././porting.html#">Writing Mod Perl scripts and Porting plain CGIs to it</A> page.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Starting_to_use_the_server">Starting to use the server</A></H1></CENTER>
<P>
Now you want to writing the cgis. You better start writing it very clean
and with understanding of the new running environment. You have to learn
how to write correctly for mod_perl. There is nothing new here, all you
have to remember that your script wouldn't die after it finishs to serve
the request, but will stay in memory and might affect all other scripts
running under the same server process (child). You will read more about it
in the following sections: <A HREF="././porting.html#">Writing Mod Perl scripts and Porting plain CGIs</A>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 12/01/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/status.html
Index: status.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Seeing the Unseen: Peeking into the Server's Inwards </TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Seeing the Unseen: Peeking into the Server's Inwards </H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Watching_the_server">Watching the server</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Watching_the_server">Watching the server</A></H1></CENTER>
<P>
Very important feature. You can dynamically watch what happens to the
server
<P>
Add this to http.conf: <Location /perl-status> SetHandler perl-script
PerlHandler Apache::Status order deny,allow #deny from all #allow from
</Location>
<P>
Then fetch <A
HREF="http://www.myserver.com:81/perl-status">http://www.myserver.com:81/perl-status</A>
<P>
<PRE> Embedded Perl version 5.00502 for Apache/1.3.2 (Unix) mod_perl/1.16
process 187138, running since Thu Nov 19 09:50:33 1998
</PRE>
<P>
<PRE> Signal Handlers
Enabled mod_perl Hooks
PerlRequire'd Files
Environment
Perl Section Configuration
Loaded Modules
Perl Configuration
ISA Tree
Inheritance Tree
Compiled Registry Scripts
Symbol Table Dump
</PRE>
<P>
Let's follow for example : PerlRequire'd Files => we see:
<P>
<PRE> PerlRequire Location
/usr/apps/pais/lib/apache-startup.pl /usr/apps/pais/lib/apache-startup.pl
</PRE>
<P>
From some menus you can continue dipper to peek into internals of the
server, to see the values of the global variables in the packages, to the
the cached scripts and modules and much more. Just click around...
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/19/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/warnings.html
Index: warnings.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Warnings and Errors you see: Were do they come from and How to fix them</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
<META NAME="Author" CONTENT="Bekman Stas">
<META NAME="Description" CONTENT="mod_perl,perl,apache">
<META NAME="Keywords" CONTENT="mod_perl,perl,apache,webserver,cgi">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<H1 ALIGN=CENTER>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
Warnings and Errors you see: Were do they come from and How to fix them</H1>
<HR WIDTH="100%">
<!-- INDEX BEGIN -->
<P><A NAME="toc"></A><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
<LI><A HREF="#Value_of_x_will_not_stay_shared">Value of $x will not stay shared at - line 5 </A>
<LI><A HREF="#Value_of_x_may_be_unavailable_a">Value of $x may be unavailable at - line 5.</A>
<LI><A HREF="#Constant_subroutine_redefine">Constant subroutine ... redefined</A>
<LI><A HREF="#Global_symbol_foo_requires_ex">Global symbol "$foo" requires explicit package name</A>
<LI><A HREF="#Can_t_undef_active_subroutine">Can't undef active subroutine</A>
<LI><A HREF="#Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A>
<LI><A HREF="#Undefined_subroutine_Apache_RO">Undefined subroutine &Apache::ROOT::perl::test_2epl::some_function called at</A>
<LI><A HREF="#Callback_called_exit">Callback called exit</A>
<LI><A HREF="#Out_of_memory_">Out of memory!</A>
</UL>
<!-- INDEX END -->
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Value_of_x_will_not_stay_shared">Value of $x will not stay shared at - line 5</A></H1></CENTER>
<P>
See <A HREF="././obvious.html#my_scoped_variable_in_the_nest">my() scoped variable in the nested subroutine</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Value_of_x_may_be_unavailable_a">Value of $x may be unavailable at - line 5.</A></H1></CENTER>
<P>
See <A HREF="././obvious.html#my_scoped_variable_in_the_nest">my() scoped variable in the nested subroutine</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Constant_subroutine_redefine">Constant subroutine ... redefined</A></H1></CENTER>
<P>
That's a mandatory warning inside Perl. It happens only if you modify your
script and Apache::Registry reloads it. Perl is warning you that the
<CODE>subroutine(s)</CODE> were redefined. It is mostly harmless. If you
don't like seeing those, just kill -USR2 (graceful restart) apache when you
modify your scripts.
<P>
<META> Someone said: You won't see that warning in this case with
5.004_05 or 5.005+.
<P>
I'm running perl5.00502 and I still get these warnings??? </META>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Global_symbol_foo_requires_ex">Global symbol "$foo" requires explicit package name</A></H1></CENTER>
<P>
A script below will print a warning like above, moreover it will print the
whole script as a part of the warning message:
<P>
<PRE> #!/usr/bin/perl -w
use strict;
print "Content-type: text/html\n\n";
print "Hello $undefined";
</PRE>
<P>
The warning:
<P>
<PRE> Global symbol "$undefined" requires explicit package name at /usr/apps/pais/cgi/tmp.pl line 4.
eval 'package Apache::ROOT::perl::tmp_2epl;use Apache qw(exit);sub handler {
#line 1 /usr/apps/pais/cgi/tmp.pl
BEGIN {$^W = 1;}#!/usr/bin/perl -w
use strict;
print "Content-type: text/html\\n\\n";
print "Hello $undefined";
}
;' called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 168
Apache::Registry::compile('package
Apache::ROOT::perl::tmp_2epl;use Apache qw(exit);sub han...')
called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 121
Apache::Registry::handler('Apache=SCALAR(0x205026c0)') called at /usr/apps/pais/cgi/tmp.pl line 4
eval {...} called at /usr/apps/pais/cgi/tmp.pl line 4
[Sun Nov 15 15:15:30 1998] [error] Undefined subroutine &Apache::ROOT::perl::tmp_2epl::handler called at /
usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 135.
[Sun Nov 15 15:15:30 1998] [error] Goto undefined subroutine &Apache::Constants::SERVER_ERROR at /usr/apps
/lib/perl5/site_perl/5.005/aix/Apache/Constants.pm line 23.
</PRE>
<P>
The error is simple to fix, you have used <CODE>use strict;</CODE> pragma, so all variables should be defined before you use them. The bad
thing is that the whole script that can be thousand lines is being printed
to error_log file as a code that the server has tried to
<CODE>eval().</CODE>
<P>
As Doug answered to this question:
<P>
<PRE> Looks like you have a $SIG{__DIE__} handler installed (Carp::confess?).
That's what's expected if so
</PRE>
<P>
It wasn't in my case, but may be yours
<P>
Bryan Miller said:
<P>
<PRE> You might wish to try something more terse such as
"local $SIG{__WARN__} = \&Carp::cluck;" The confess method is _very_
verbose and will tell you more than you might wish to know including
full source.
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Can_t_undef_active_subroutine">Can't undef active subroutine</A></H1></CENTER>
<P>
Can't undef active subroutine at
/usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 102. Called
frompackage Apache::Registry, filename
/usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm, line 102
<P>
META: ?
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A></H1></CENTER>
<P>
If you compile with the experimental PERL_MARK_WHERE=1, it shows you
``exactly'' where this is happening. many times compiler makes a shift for
``unknown'' reasons in it's line counter. You can always stuff you code
with special compiler directives, to reset it's counter to the value you
will tell. At the beginning of the line you should write (# sticked to the
leftmost side):
<P>
<PRE> #line 298 myscript.pl
</PRE>
<P>
(myscript.pl is optional). It specifies the line number of the _following_
line, not the line the directive is on. You can use a little script to
stuff every N lines of your code with this directives, but then you will
have to rerun this script everytime you add remove code lines. The script:
<P>
<PRE> #!/usr/bin/perl
# Puts Perl line markers in a Perl program for debugging purposes.
# Also takes out old line markers.
die "No filename to process.\n" unless @ARGV;
my $filename = $ARGV[0];
my $lines = 100;
open IN, $filename or die "Cannot open file: $filename: $!\n";
open OUT, ">$filename.marked" or die "Cannot open file: $filename.marked: $!\n";
my $counter = 1;
while (<IN>) {
print OUT "# line $counter\n" unless $counter++ % $gap;
next if $_ =~ /^# line /;
print OUT $_;
$counter++;
}
close OUT;
close IN;
chmod 0755, "$filename.marked";
</PRE>
<P>
You can also add:
<P>
<PRE> use Carp ();
local $SIG{__WARN__} = \&Carp::cluck;
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Undefined_subroutine_Apache_RO">Undefined subroutine &Apache::ROOT::perl::test_2epl::some_function called at</A></H1></CENTER>
<P>
See <A HREF="././porting.html#Names_collisions_with_Modules_an">Names collisions with Modules and libs</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Callback_called_exit">Callback called exit</A></H1></CENTER>
<P>
See <A HREF="#Out_of_memory_">Out_of_memory!</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Out_of_memory_">Out of memory!</A></H1></CENTER>
<P>
If something goes really wrong with your code, Perl may die with an ``Out
of memory!'' message and or ``Callback called exit''. A common cause of
this are never-ending loops, deep recursion or calling an undefined
subroutine. Here's one way to catch the problem: See Perl's INSTALL
document for this item:
<P>
<PRE> =item -DPERL_EMERGENCY_SBRK
</PRE>
<P>
<PRE> If PERL_EMERGENCY_SBRK is defined, running out of memory need not be a
fatal error: a memory pool can allocated by assigning to the special
variable $^M. See perlvar(1) for more details.
</PRE>
<P>
If you compile with that option and add 'use Apache::Debug level => 4;'
to your PerlScript, it will allocate the $^M emergency pool and the
$SIG{__DIE__} handler will call Carp::confess, giving you a stack trace
which should reveal where the problem is. See the Apache::Resource module
for prevention of spinning httpds.
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P><A HREF="index.html">[Back to the main page]</A></P>
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
<HR>
</TD>
</TR>
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER>
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
<BR>Last Modified at 11/24/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" HEIGHT=30 WIDTH=90></A>
</TD>
<TD>
<FONT SIZE=-2>
Use of the Camel for Perl is <BR>
a trademark of <A HREF="http://www.ora.com">O'Reilly & Associates</A>,<BR>
and is used by permission.
</FONT>
</TD>
</TR>
</TABLE></CENTER>
</BODY>
</HTML>
1.1 modperl-site/guide/images/mod_perl.gif
Index: mod_perl.gif
===================================================================
GIF89aZ
5��SČ9����wDH�1�E,�>nA�
h�P-iš0��۴�P�!��TX��87c�PF<=��. ��V�� x�\�����C�|������O_5a�
�(#�#ƗA�
�A[=nAJ���^UMj�s�MY���]�h�F.�VqE�U�V�U
1.1 modperl-site/guide/images/mod_perl2.jpg
Index: mod_perl2.jpg
===================================================================
����
��
g�?�T�W��:N?M?��D���a�.x!��{���>W��/F)�k�}>���8qˋ � �)���������R^z?ƶC���5���t�o��[�����G��r�m�׳�����ֳq���j��3���
��~�
�kX��4�eo���}�o�v�n^����
�z2)������^��E��
��
��
<`M*�""TN*��)�e�3�o'-э����T�����Q���c>Z�M�h�Â�*:���ef��'��N)�3!��GXpm| W�
G�s��8
�F:����&�C�5MÞW0纉�2�9-�U�+t��EV��d�'��2(�ť����5o�ŏ%o{hT��ݮ�
D�#�1b�1���:�<�Z
=W��ҙ�➈�֥4Q��yۑ4�ܻ��VX�2�l�� ����j*;���j�3
��0�V�}:�(��H�-m�
8�]��4
t<�5>�l<�UїSsa��"�퐚t7�p�r�ɴė��SK*�sdO�Ԁ'�.����C�?/&<�M��6��!����T� �<\i�(�bd)����[Y��q;i�'?4UV�l]�T�x|���eG�ېBs�šU
J`r��WoC�+�@�h�� \^��bDj+=ȡ���JPL>,�f�uWm,y��[�Ϣ�Rq�
h�r���
����yX�z�V�ķ���L}��k��)���u���Ҩ��qB�(�����ː�p'�RhR���
�㪽����ݔ�|���w}���L{�Gi�N35�Rߨq�BTE��t���py��&�?h�Z;�Y{b�C�N�~O�֟3�iD�/Lh�&+fn+M���v�)r��A��@��q�A�x�uE4��G�;���7�[�ޮ�� �V�^S�ƽ�iTQ��E�QD!EQQEBQE���