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/07 14:03:12 UTC
cvs commit: modperl-site/guide CHANGES all.html 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
sbekman 98/12/07 05:03:12
Modified: 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
Added: guide CHANGES all.html
Log:
* Run a spell check. ispell and WWWebster were quite helpful :)
* Added Richard Dice's notes about ways to see whether or not mod_perl
is actually compiled into the server and working. "check the
error_log file" (installation)
* Added 'Is it possible to install mod_perl without root access?'
section into Server Installtion (scenario) page.
* Added Perrin Harkins and Jonathan Peterson's notes about
apache/mod_perl/embperl/DBI vs IIS/ASP/ADO
* Added a CHANGES file (this one)
* Added an 'all in one page', suitable for printing. Currently it's
just an ordered cat(). In the future it might change :)
Revision Changes Path
1.3 +6 -6 modperl-site/guide/config.html
Index: config.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/config.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- config.html 1998/12/03 21:04:21 1.2
+++ config.html 1998/12/07 13:03:06 1.3
@@ -53,7 +53,7 @@
configure server's configuration files. To learn how to configure the
apache's config files, please the use the apache's documentation or just
open the files in conf directory and follow the instructions in these files
-- they are selfexplainable...
+- they are self explainable...
<P>
Before you start configuration of mod_perl, configure the apache, and see
@@ -101,7 +101,7 @@
and then to put it back!!!
<P>
-Ofcourse you can choose any other alias (you will use it later in
+Of course you can choose any other alias (you will use it later in
http.conf), you can choose to use all 3 modes or only one of these (It's
unlikely to run plain cgi-bin scripts from mod_perl server - the price is
too high, you better run these at plain apache server. See
@@ -135,7 +135,7 @@
<P>
<CODE>PerlSendHeader On</CODE> tells the server to send an HTTP header to the browser, on every script
-envocation. You will want to turn it off for you nph (non-parsed-headers)
+invocation. You will want to turn it off for you nph (non-parsed-headers)
scripts.
<P>
@@ -238,8 +238,8 @@
<CENTER><H2><A NAME="What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A></H2></CENTER>
<P>
Modules that are being loaded at the server startup will be shared among
-server childs, so only one copy of each module will be loaded, thus saving
-a lot of RAM for you.
+server children, so only one copy of each module will be loaded, thus
+saving a lot of RAM for you.
<P>
See <A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
@@ -380,7 +380,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.3 +23 -23 modperl-site/guide/control.html
Index: control.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/control.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- control.html 1998/12/03 21:04:21 1.2
+++ control.html 1998/12/07 13:03:06 1.3
@@ -151,7 +151,7 @@
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
+It's important to understand that this script is 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.
@@ -226,8 +226,8 @@
Another approach, probably even more practical, is to use the Cool LWP perl
package , to test the server by trying to fetch some document (script)
served by the server. Why is it more practical? Since the while server can
-be up as a process, it can be stucked and not working (SYN_RECV state -
-anyone???), So failing to get the document will trigger restrart, and
+be up as a process, it can be stuck and not working (SYN_RECV state -
+anyone???), So failing to get the document will trigger restart, and
``probably'' the problem will go away. (Just replace <CODE>start</CODE> with <CODE>restart</CODE> in the <CODE>$restart_command</CODE> below.
<P>
@@ -269,7 +269,7 @@
# print "Status $status\n";
my $message = ($status == 0)
- ? "Server was down and sucessfully restarted!"
+ ? "Server was down and successfully restarted!"
: "Server is down. Can't restart.";
</PRE>
<P>
@@ -285,7 +285,7 @@
</PRE>
<P>
<PRE> # input: URL to check
- # output: 1 if sucess, o for fail
+ # output: 1 if success, o for fail
#######################
sub checkurl{
my ($url) = @_;
@@ -324,7 +324,7 @@
<P>
<PRE> <META>
Is it possible to make the server do something when it dies? e.g
- restart itself :) NO, really when it dies , (killed in inproper way?)
+ restart itself :) NO, really when it dies , (killed in improper way?)
is it possible to trigger some action?
</PRE>
<P>
@@ -370,7 +370,7 @@
<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
+many times you have a group of developers who need to concurrently 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
@@ -413,9 +413,9 @@
</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
+So what we have achieved with this technique is: A full control over
+start/stop, number of children, 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>
@@ -430,7 +430,7 @@
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
+Of course 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.
@@ -484,13 +484,13 @@
<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:
+Of course you have another problem: The cgi generates some html, which
+should be called again. If it generates a URL with hard coded 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
+redirect (which is transparent for user) but it will not work if you have
something to POST (redirect looses all the data!)
<P>
@@ -510,12 +510,12 @@
<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
+Many times you start off 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
+variable which includes paths that aren't in the <CODE>@INC</CODE> of the
perl compiled with mod_perl server and configured during the startup.
<P>
@@ -524,8 +524,8 @@
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
+completely 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
@@ -537,7 +537,7 @@
# This is a wrapper example
- # It simulates the webserver environment by setting the @INC and other
+ # It simulates the web server environment by setting the @INC and other
# stuff, so what will run under this wrapper will run under web and
# vice versa.
@@ -583,14 +583,14 @@
}
# run the cgi from the script's directory
- # Note that we envoke warnings and Taintness ON!!!
+ # Note that we invoke 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.
+A little bit off topic but good to know.
<P>
To rotate the logs do:
@@ -619,7 +619,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.3 +2 -2 modperl-site/guide/debug.html
Index: debug.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/debug.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- debug.html 1998/12/03 21:04:21 1.2
+++ debug.html 1998/12/07 13:03:06 1.3
@@ -49,7 +49,7 @@
<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.
+ g - Trace global variable handling, interpreter construction, END blocks, etc.
all - all of the above
</PRE>
<P>
@@ -72,7 +72,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.4 +9 -7 modperl-site/guide/help.html
Index: help.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/help.html,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- help.html 1998/12/07 04:17:14 1.3
+++ help.html 1998/12/07 13:03:07 1.4
@@ -101,15 +101,17 @@
<LI>mod_perl mailing list</LI>
-<P>The Apache/Perl mailing list (modperl@apache.org) <B>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 <a href="mailto:majordomo@apache.org">majordomo@apache.org</a>
-with the string "subscribe modperl" in the body. </P>
+<P>The Apache/Perl mailing list (modperl@apache.org) <B>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 <a
+href="mailto:majordomo@apache.org">majordomo@apache.org</a> 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>
+<P><B>Searchable </B>mod_perl mailing list<A
+HREF="http://forum.swarthmore.edu/epigone/modperl"><B>archive</B></A>by
+Ken Williams. </P>
</UL>
1.3 +10 -2 modperl-site/guide/index.html
Index: index.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/index.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- index.html 1998/12/03 21:04:22 1.2
+++ index.html 1998/12/07 13:03:07 1.3
@@ -15,7 +15,7 @@
to your perl cgi-bin scripts.</B></P></CENTER>
-<CENTER><P><B>Version 1.00 Dec, 3 1998</B></P></CENTER>
+<CENTER><P><B>Version 1.01 Dec, 7 1998</B></P></CENTER>
<P>
@@ -62,7 +62,15 @@
<LI><A HREF="snippets.html">Code Snippets</A></LI>
-<LI><A HREF="help.html">Help. Futher Learning.</A></LI>
+<LI><A HREF="help.html">Help. Further Learning.</A></LI>
+
+
+<LI><A HREF="all.html">Guide All in One. Ready for Printing</A></LI>
+
+
+<LI><A HREF="CHANGES">CHANGES</A></LI>
+
+
</UL>
1.4 +9 -8 modperl-site/guide/intro.html
Index: intro.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/intro.html,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- intro.html 1998/12/07 04:17:14 1.3
+++ intro.html 1998/12/07 13:03:07 1.4
@@ -30,7 +30,7 @@
<LI><A HREF="#2">What is covered in this document</A></LI>
-<LI><A HREF="#3">Sources and Acknowlegements</A></LI>
+<LI><A HREF="#3">Sources and Acknowledgments</LI>
</UL>
@@ -68,7 +68,7 @@
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
+(see <A HREF="http://perl.apache.org/tidbits.html">Tidbit </A>and <A HREF="http://perl.apache.org/stories/">Stories
</A>pages for the facts)</P>
@@ -79,10 +79,10 @@
<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
+<P>This document was written 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
+web server 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>
@@ -94,7 +94,7 @@
(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
+configuration notes, which will help you to successfully
complete the mod_perl installation.</P>
@@ -120,7 +120,7 @@
<HR WIDTH="100%"></P>
-<H3 ALIGN=CENTER><A NAME="3"></A>Sources and Acknowledgements</H3>
+<H3 ALIGN=CENTER><A NAME="3"></A>Sources and Acknowledgments</H3>
<P>This document is based on:</P>
@@ -152,6 +152,7 @@
href="http://perl.apache.org/src/mod_perl-1.16/SUPPORT">SUPPORT</a>
file in the distribution)</LI>
+
<LI>My personal experience with mod_perl</LI>
</UL>
@@ -159,7 +160,7 @@
<P>As I said, I've quoted many information 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
+ track of names, and became lost, so I preferred 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>
@@ -199,7 +200,7 @@
<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
+bug patches, modules and help. And of course the numeral unseen users who
helped to find the bugs and advocate mod_perl around the world.</P>
1.3 +17 -17 modperl-site/guide/obvious.html
Index: obvious.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/obvious.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- obvious.html 1998/12/03 21:04:22 1.2
+++ obvious.html 1998/12/07 13:03:07 1.3
@@ -102,13 +102,13 @@
<CODE>&y</CODE> is called only from inside &x.
<P>
-(this was partitially extracted from perl5-porters post)
+(this was partially 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
+That's exactly the point that is not obvious. 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!
@@ -157,16 +157,16 @@
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.
+you apply are immediately 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
+assumes that it wasn't, thus saving a few millisecs 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
+script that doesn't require 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?
@@ -343,7 +343,7 @@
text to ensure the match succeeds, you have two possibilities.
<P>
-If you can guaranteee that the pattern variable contains no meta-characters
+If you can guarantee that the pattern variable contains no meta-characters
(things like *, +, ^, $...), you can use the dummy match:
<P>
@@ -361,8 +361,8 @@
Phil. Chu contributed this:
<P>
-It depends on the complexity of the regex you apply this technique to. One
-common usage where compiled regex is usually more efficient is to ``match
+It depends on the complexity of the regexp you apply this technique to. One
+common usage where compiled regexp is usually more efficient is to ``match
any one of a group of patterns'' over and over again.
<P>
@@ -428,14 +428,14 @@
multiply server environment will result in something like 1,9,4,19 (number
per reload), since ``each'' time your script will be served by a different
child. (On some OSes parent process assign all the requests to the same
-child process if all of the childs are idle... AIX...). But if you run in
+child process if all of the children are idle... AIX...). But if you run in
httpd -X single server mode you will get 2,3,4,5... (taken that the
<CODE>random()</CODE> returned 1 at the first call)
<P>
But don't get too obsessive with 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:
+server mode sometimes hides problems that show up when you switch to multi
+server mode. Assume the following code:
<P>
Application that allows you to change the configuration at the run time.
@@ -445,12 +445,12 @@
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 ,
+a problem... If you run the same code in the multi server 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
+Just remember that children can't share information, but the stuff they
inherited from parent on their load.
<P>
@@ -465,8 +465,8 @@
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.
+was started before the file was created and it's a normal behavior with any
+perl.
<P>
If you want to have -M test to count the time relative to the current
@@ -487,7 +487,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.3 +94 -12 modperl-site/guide/performance.html
Index: performance.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/performance.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- performance.html 1998/12/03 21:04:23 1.2
+++ performance.html 1998/12/07 13:03:07 1.3
@@ -25,10 +25,11 @@
<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_Impressing_your_Boss">Benchmarks. Impressing your Boss and Collegues.</A>
+ <LI><A HREF="#Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A>
<UL>
- <LI><A HREF="#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistant DB Connection</A>
+ <LI><A HREF="#Developers_Talk">Developers Talk</A>
+ <LI><A HREF="#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A>
<LI><A HREF="#Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A>
<LI><A HREF="#PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A>
</UL>
@@ -196,7 +197,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Collegues.</A></H1></CENTER>
+<CENTER><H1><A NAME="Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A></H1></CENTER>
<P>
How much faster is mod_perl that CGI? There are many ways to benchmark the
two. See a few examples and numbers below, also checkout the benchmark/
@@ -208,7 +209,7 @@
<P>
There is no need to write a special benchmark, if you want to impress your
-boss or collegues, just take the heaviest cgi script you have, open 2
+boss or colleagues, just take the heaviest cgi script you have, open 2
xterms and call the same script in mod_perl mode in one xterm and in
mod_cgi mode in the other. You can use lwp-get from LWP package to emulate
the web agent (browser). (benchmark/ directory of mod_perl dist includes
@@ -216,8 +217,88 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistant DB Connection</A></H2></CENTER>
+<CENTER><H2><A NAME="Developers_Talk">Developers Talk</A></H2></CENTER>
<P>
+Perrin Harkins writes on benchmarks or comparisons, official or unofficial:
+
+<BLOCKQUOTE>
+
+<P>
+I have used some of the platforms you mentioned and researched others. What
+I can tell you for sure, is that no commercially available system offers
+the depth, power, and ease of use that mod_perl has. Either they don't let
+you access the web server internals, or they make you use less productive
+languages than Perl, sometimes forcing you into restrictive and confusing
+APIs and/or GUI development environments. None of them offer the level of
+support available from simply posting a message to this list, at any price.
+
+<P>
+As for performance, beyond doing several important things (code-caching,
+pre-forking/threading, and persistent database connections) there isn't
+much these tools can do, and it's mostly in your hands as the developer to
+see that the things which really take the time (like database queries) are
+optimized.
+
+<P>
+The downside of all this is that most manager types seem to be unable to
+believe that web development software available for free could be better
+than the stuff that cost $25,000 per CPU. This appears to be the major
+reason most of the web tools companies are still in business. They send a
+bunch of suits to give PowerPoint presentations and hand out glossy
+literature to your boss, and you end up with an expensive disaster and an
+approaching deadline.
+
+<P>
+But I'm not bitter or anything...
+
+</BLOCKQUOTE>
+
+<P>
+Jonathan Peterson adds:
+
+<BLOCKQUOTE>
+
+<P>
+Most of the major solutions have something that they do better than the
+others, and each of them has faults. Microsofts ASP has a very nice objects
+model, and has IMO the best data access object (better than DBI to use -
+but less portable) It has the worst scripting language. PHP has many of the
+advantages of Perl-based solutions, but is less complicated for developers.
+Netscape's Livewire has a good object model too, and provides good
+server-side Java integration - if you want to leverage Java skills, it's
+good. Also, it has a compiled scripting language - which is great if you
+aren't selling your clients the source code (and a pain otherwise).
+
+<P>
+mod_perl's advantage is that it is the most powerful. It offers the
+createst degree of control with one of the more powerful languages. It also
+offers the greatest granularity. You can use an embedding module (eg eperl)
+from one place, a session module (Session) from another, and your data
+acces module from yet another.
+
+<P>
+I think the Apache::ASP module looks very promising. It has very easy to
+use and adequately powerful state maintenance, a good embedding system, and
+a sensible object model (that emulates the Microsoft ASP one). It doesn't
+replicate MS's ADO for data access, but DBI is fine for that.
+
+<P>
+I have always found that the developers available make the greatest impact
+on the decision. If you have a team with no Perl experience, and a small or
+medium task, using something like PHP, or Microsoft ASP, makes more sense
+than driving your staff into the vertical learning curve they'll need to
+use mod_perl.
+
+<P>
+For very large jobs, it may be worth finding the best technical solution,
+and then recruiting the team with the necessary skills.
+
+</BLOCKQUOTE>
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A></H2></CENTER>
+<P>
Here are the numbers from Michael Parker's mod_perl presentation at Perl
Conference (Aug, 98) <A
HREF="http://www.realtime.net/~parkerm/perl/conf98/index.htm">http://www.realtime.net/~parkerm/perl/conf98/index.htm</A>
@@ -256,7 +337,7 @@
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A></H2></CENTER>
<P>
-As noted before for very fast scripts you will ahev to use Time::HiRes
+As noted before for very fast scripts you will have to use Time::HiRes
module, it's usage is similar to the Benchmark's.
<P>
@@ -279,7 +360,7 @@
<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
+Another popular use of mod_perl is to take advantage of it's persistence to
maintain open database connections. The basic idea goes like so:
<P>
@@ -296,7 +377,7 @@
perform <CODE>disconnect().</CODE>
<P>
-Be carefull to use different names for handlers if you open connection to
+Be careful to use different names for handlers if you open connection to
different Databases!
<P>
@@ -345,7 +426,7 @@
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.
+to see the requirements for this method.
<P>
However be warned that some old DBD drivers aren't supporting this feature
@@ -359,7 +440,7 @@
<P>
Also some folks at list suggested to change the timeout of the server (they
-talked specificly about mysql). So starting from 3.22.x you can set a
+talked specifically about mysql). So starting from 3.22.x you can set a
wait_timeout option at mysqld server startup to change the default value,
setting it to 24 hours probably will fix the timeout problem.
@@ -636,7 +717,8 @@
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>
+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%" >
@@ -650,7 +732,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.4 +39 -39 modperl-site/guide/porting.html
Index: porting.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/porting.html,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- porting.html 1998/12/07 04:17:14 1.3
+++ porting.html 1998/12/07 13:03:07 1.4
@@ -47,7 +47,7 @@
<LI><A HREF="#Code_has_been_changed_but_seems">Code has been changed, but seems that script uses the old code</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>
+ <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>
<LI><A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
</UL>
@@ -63,11 +63,11 @@
<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.
+you might encounter when running the existent 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.
+to learn most of the possible pitfalls and to avoid them in first place.
<P>
It covers also the case when the script is too dirty, but does the job and
@@ -140,7 +140,7 @@
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
+parameters passed to <CODE>require().</CODE> And values are the real paths
to these modules. So if you do (assume it's in the <CODE>@INC</CODE> path)
<P>
@@ -268,7 +268,7 @@
<P><LI>
<P>
-Declare a package in the required files! (Ofcourse it should be unique to
+Declare a package in the required files! (Of course 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!
@@ -489,10 +489,10 @@
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:
+line arguments have a equivalent special variable. For example, the $^W
+variable corresponds to the -w switch. Consult perlvar for more details.
+With mod_perl it is also possible to turn on warnings globally via the
+PerlWarn directive:
<P>
<PRE> PerlWarn On
@@ -647,11 +647,11 @@
</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
+exactly by that size. Now if you have 20 children 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,
+possible of course. Try to process line at a time and print it back to the
+file (if you need to modify the file itself, use temporary file for that,
when finished overwrite the src file, make sure to provide locking
mechanism!)
@@ -661,13 +661,13 @@
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
+copied another 5M and the child has grew up 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>
@@ -702,7 +702,7 @@
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)....
+not possible to update)....
<P>
<STRONG>Third example</STRONG> is work with DataBases. If you do some DB processing, many times you have
@@ -725,8 +725,8 @@
</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!)
+variables that have been allocated for the records that matched the query.
+(Again remember to multiply it by the number of the children server runs!)
<P>
What you want to do is to not accumulate the records but print them as they
@@ -760,7 +760,7 @@
<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
+very flexible, since it accepts: conditions, callback closure sub, select
fields and restrictions.
<P>
@@ -809,7 +809,7 @@
</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
+what stage are we in: header, body or tail. For example a callback closure
for formatting the rows we want to print:
<P>
@@ -822,7 +822,7 @@
my $counter = 0;
my %cols = (); # columns name=> value hash
- # Closure with the following behaviour:
+ # Closure with the following behavior:
# 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
@@ -880,7 +880,7 @@
<P>
Generally the problem you have is using global variables. Since global
-variables don't change from one script envocation to another unless you
+variables don't change from one script invocation to another unless you
change it, you can find your scripts do ``fancy'' things.
<P>
@@ -896,7 +896,7 @@
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
+of the program and voila 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:
@@ -908,7 +908,7 @@
authenticate($username,$passwd);
# failed, break out
die "Wrong passwd" unless $authenticated == 1;
- # user is Ok, fetch user's data
+ # user is OK, fetch user's data
show_user($username);
</PRE>
<P>
@@ -921,15 +921,15 @@
<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!
+successfully 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!
+other different solution). Of course the example is too trivial - but
+believe me it happens!
<P>
-Just another little one linner that can make your day spoiled, assuming you
+Just another little one liner that can make your day spoiled, assuming you
forgot to reset the $allowed. It's perfectly OK in plain mod_cgi :
<P>
@@ -942,11 +942,11 @@
<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
+use a different pattern that will be used in regexp 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
+the child who has already cached the regexp 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
+(new fresh child) and then it doesn't (child that already cached the regexp
and wouldn't recompile because of /o).
<P>
@@ -957,7 +957,7 @@
<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>
+<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.
@@ -1006,7 +1006,7 @@
inside of a subroutine. Scripts will be ``compiled'' on each request. After
the script has run, it's namespace is flushed of all variables and
subroutines. Still, you don't have the overhead of loading the perl and
-compilation time of the standart modules (If your script is very light, but
+compilation time of the standard modules (If your script is very light, but
uses lots of standard modules - you will see no difference between
Apache::PerlRun and Apache::Registry !).
@@ -1074,7 +1074,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.3 +53 -5 modperl-site/guide/scenario.html
Index: scenario.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/scenario.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- scenario.html 1998/12/03 21:04:24 1.2
+++ scenario.html 1998/12/07 13:03:07 1.3
@@ -27,6 +27,7 @@
<LI><A HREF="#httpd_perl_server_mod_perl_">httpd_perl server (mod_perl):</A>
</UL>
+ <LI><A HREF="#Is_it_possible_to_install_mod_pe">Is it possible to install mod_perl without root access?</A>
</UL>
<!-- INDEX END -->
@@ -194,8 +195,8 @@
<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)
+Now update the apachectl utility 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
@@ -205,6 +206,18 @@
<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>
+Before you start to configure the mod_perl, you should be aware that there
+a few reqired modules that have to be installed before. You will know
+whether you have all the required installed or not, during the run <CODE>perl Makefile.PL</CODE> below. If you discover that you don't have these, go to your nearest CPAN
+repository (if you don't know what is it, go to <A
+HREF="http://www.perl.com/CPAN">http://www.perl.com/CPAN</A> ) or run the
+interactive shell by
+<CODE>perl -MCPAN -e shell</CODE> .
+
+<P>
+Now back to installation.
+
+<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
@@ -249,14 +262,49 @@
<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)
+now update the apachectl utility 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>
Now proceed to <A HREF="././config.html#">Server Configuration</A> section.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Is_it_possible_to_install_mod_pe">Is it possible to install mod_perl without root access?</A></H1></CENTER>
+<P>
+Yes, no problem with that. Follow the instructions above and when you
+encounter APACI_ARGS use your home directory or alike as a prefix (e.g
+<CODE>/home/stas/www</CODE>) and everything will be installed there. There is a chance that some perl
+libs will be not installed on your server by root and you will have to
+install these locally too. See the <A
+HREF="http://www.esafe.com/stas/TULARC/webmaster/myfaq.html#7">http://www.esafe.com/stas/TULARC/webmaster/myfaq.html#7</A>
+for more information on local perl installations.
+
+<P>
+You will not be able to set the server to listen to port lower then 1024
+(if you aren't a root). So pick your port as a number above the 1024. (I
+use 8080 in most cases). Note that you will have to use the <A
+HREF="http://www.you.com:8080">http://www.you.com:8080</A> in that case.
+But it's not a problem since generally users don't access directly the cgi
+but from the webpage, so they shouldn't know at all that the port is
+different.
+
+<P>
+You will need to worry to put the start server script into rc.d directory
+of your machine, so if the last will be rebooted - your webserver will be
+restarted automatically.
+
+<P>
+One more important thing is Resources, mod_perl is very memory greedy and
+if you will run lots of mod_perl processes on that machine, most likely
+your host will ask you to shutdown the mod_perl server, or to find another
+home. You have a few solutions: <STRONG>a.</STRONG> reduce resource usage - see <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A> <STRONG>b.</STRONG> ask your ISP if you can put a dedicated machine into their computer room
+and be root there. <STRONG>c.</STRONG> look for another ISP with lots of resources or one that supports mod_perl
+(not likely)
+
<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>
@@ -271,7 +319,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.3 +1 -1 modperl-site/guide/snippets.html
Index: snippets.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/snippets.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- snippets.html 1998/12/03 21:04:24 1.2
+++ snippets.html 1998/12/07 13:03:08 1.3
@@ -63,7 +63,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/02/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.3 +19 -11 modperl-site/guide/start.html
Index: start.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/start.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- start.html 1998/12/03 21:04:24 1.2
+++ start.html 1998/12/07 13:03:08 1.3
@@ -38,6 +38,7 @@
<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_checking_the_error_lo">Testing by checking the error_log file</A>
<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>
@@ -53,7 +54,7 @@
<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
+the required tools. For a kick start tutorial, which will allow you make to
make copy and paste slick installation, see
<A HREF="././scenario.html#">Real World Scenario</A>
@@ -122,8 +123,8 @@
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.
+have to open the source distribution of apache preferably at the same level
+with modperl distribution.
<P>
<PRE> % ls -l /usr/src
@@ -185,12 +186,19 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Testing_by_checking_the_error_lo">Testing by checking the error_log file</A></H2></CENTER>
+<P>
+<PRE> [Thu Dec 3 17:27:52 1998] [notice] Apache/1.3.1 (Unix) mod_perl/1.15 configured -- resuming normal operations
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+</PRE>
+<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
+<Location /perl-status> Section in the server config file (refer to
<A HREF="././config.html#">ModPerlConfiguration</A>)
<P>
@@ -224,13 +232,13 @@
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.
+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. Of
+course 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
+scripts. You will find the configuration assistance at
<A HREF="././config.html#">ModPerlConfiguration</A>
@@ -310,8 +318,8 @@
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="with_lwp_request">with lwp-request</A></H2></CENTER>
<P>
-Yet another one. Why do I show all these apporoaches? While here they are
-serving a very simple purpose, they can be helpfull in other situations.
+Yet another one. Why do I show all these approaches? While here they are
+serving a very simple purpose, they can be helpful in other situations.
<P>
Assuming you have the libwww-perl package installed (LWP), you will need it
@@ -336,7 +344,7 @@
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
+have to remember that your script wouldn't die after it finishes 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>
@@ -355,7 +363,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.3 +2 -2 modperl-site/guide/status.html
Index: status.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/status.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- status.html 1998/12/03 21:04:24 1.2
+++ status.html 1998/12/07 13:03:08 1.3
@@ -32,7 +32,7 @@
<P>
<CENTER><H1><A NAME="Watching_the_server">Watching the server</A></H1></CENTER>
<P>
-Very usefull feature. You can watch what happens to the perl parts of the
+Very useful feature. You can watch what happens to the perl parts of the
server. Below you will find the instructions of configuration and usage of
this feature
@@ -105,7 +105,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.3 +7 -7 modperl-site/guide/warnings.html
Index: warnings.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/warnings.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- warnings.html 1998/12/03 21:04:24 1.2
+++ warnings.html 1998/12/07 13:03:08 1.3
@@ -93,9 +93,9 @@
The warning:
<P>
-<PRE> Global symbol "$undefined" requires explicit package name at /usr/apps/pais/cgi/tmp.pl line 4.
+<PRE> Global symbol "$undefined" requires explicit package name at /usr/apps/foo/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
+ #line 1 /usr/apps/foo/cgi/tmp.pl
BEGIN {$^W = 1;}#!/usr/bin/perl -w
use strict;
print "Content-type: text/html\\n\\n";
@@ -107,8 +107,8 @@
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
+ Apache::Registry::handler('Apache=SCALAR(0x205026c0)') called at /usr/apps/foo/cgi/tmp.pl line 4
+ eval {...} called at /usr/apps/foo/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.
@@ -148,7 +148,7 @@
<CENTER><H1><A NAME="Can_t_undef_active_subroutine">Can't undef active subroutine</A></H1></CENTER>
<P>
<PRE> 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
+ Called from package Apache::Registry, filename /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm, line 102
</PRE>
<P>
This problem is caused when, a client drops the connection while httpd is
@@ -177,7 +177,7 @@
(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:
+have to rerun this script every time you add remove code lines. The script:
<P>
<PRE> #!/usr/bin/perl
@@ -261,7 +261,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="mailto:sbekman@iil.intel.com">Stas Bekman</A>.
- <BR>Last Modified at 12/03/98
+ <BR>Last Modified at 12/07/98
</FONT>
</B>
</TD>
1.1 modperl-site/guide/CHANGES
Index: CHANGES
===================================================================
This is a CHANGES file for mod_perl mini_guide
12.07.98
* Run a spell check. ispell and WWWebster were quite helpful :)
* Added Richard Dice's notes about ways to see whether or not mod_perl
is actually compiled into the server and working. "check the
error_log file" (installation)
* Added 'Is it possible to install mod_perl without root access?'
section into Server Installtion (scenario) page.
* Added Perrin Harkins and Jonathan Peterson's notes about
apache/mod_perl/embperl/DBI vs IIS/ASP/ADO
* Added a CHANGES file (this one)
* Added an 'all in one page', suitable for printing. Currently it's
just an ordered cat(). In the future it might change :)
12.03.98
* First Release
1.1 modperl-site/guide/all.html
Index: all.html
===================================================================
<HTML><BODY BGCOLOR="white"><CENTER>
<H1>This page includes all the guide and is suitable for printing only!</H1>
</CENTER><HR>
<!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>
<CENTER><P><B>Version 1.01 Dec, 7 1998</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. Credits.</A></LI>
<LI><A HREF="start.html">Getting Started with mod_perl. Overview.</A></LI>
<LI><A HREF="scenario.html">Server Installation. Real World scenario</A></LI>
<LI><A HREF="config.html">Server Configuration</A>.</LI>
<LI><A HREF="control.html">Server Controlling and Monitoring</A></LI>
<LI><A HREF="porting.html">CGI => mod_perl Porting. mod_perl 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: Where and Why.</A>? </LI>
<LI><A HREF="performance.html">Performance. Benchmarks.</A> </LI>
<LI><A HREF="status.html">mod_perl Status. Peeking into the Server's Perl Inwards</A></LI>
<LI><A HREF="debug.html">Code Debugging techniques</A></LI>
<LI><A HREF="snippets.html">Code Snippets</A></LI>
<LI><A HREF="help.html">Help. Further Learning.</A></LI>
<LI><A HREF="all.html">Guide All in One. Ready for Printing</A></LI>
<LI><A HREF="CHANGES">CHANGES</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 12/04/1998 </FONT></B></TD>
<TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" BORDER=0 ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl mini-guide: Introduction. Incentives. 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. 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 Acknowledgments</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">Tidbit </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 written 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
web server 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 successfully
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 Acknowledgments</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>. (Subscription information is in the <a
href="http://perl.apache.org/src/mod_perl-1.16/SUPPORT">SUPPORT</a>
file in the distribution)</LI>
<LI>My personal experience with mod_perl</LI>
</UL>
<P>As I said, I've quoted many information 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 preferred 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 of course 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 12/04/1998 </FONT></B></TD>
<TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" BORDER=0 ALT="Mod Perl Icon" HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Getting Started with mod_perl. Overview.</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. Overview.</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_checking_the_error_lo">Testing by checking the error_log file</A>
<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>
<LI><A HREF="#with_lwp_request">with lwp-request</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 kick start tutorial, which 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 preferably 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_checking_the_error_lo">Testing by checking the error_log file</A></H2></CENTER>
<P>
<PRE> [Thu Dec 3 17:27:52 1998] [notice] Apache/1.3.1 (Unix) mod_perl/1.15 configured -- resuming normal operations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
</PRE>
<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 (refer 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. Of
course 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 configuration 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><H2><A NAME="with_lwp_request">with lwp-request</A></H2></CENTER>
<P>
Yet another one. Why do I show all these approaches? While here they are
serving a very simple purpose, they can be helpful in other situations.
<P>
Assuming you have the libwww-perl package installed (LWP), you will need it
installed for passing the mod_perl's <CODE>make test</CODE> anyway.
<P>
<PRE> % lwp-request -e -d www.site.com
</PRE>
<P>
Will show you all the headers.
<P>
<PRE> % lwp-request -e -d www.site.com | egrep '^Server:'
</PRE>
<P>
To see the server's version only.
<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 finishes 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/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Server Installation. 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>
Server Installation. 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>
<LI><A HREF="#Is_it_possible_to_install_mod_pe">Is it possible to install mod_perl without root access?</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="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 utility 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>
Before you start to configure the mod_perl, you should be aware that there
a few reqired modules that have to be installed before. You will know
whether you have all the required installed or not, during the run <CODE>perl Makefile.PL</CODE> below. If you discover that you don't have these, go to your nearest CPAN
repository (if you don't know what is it, go to <A
HREF="http://www.perl.com/CPAN">http://www.perl.com/CPAN</A> ) or run the
interactive shell by
<CODE>perl -MCPAN -e shell</CODE> .
<P>
Now back to installation.
<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>
rename the 'httpd' to 'http_perl'
<P>
<PRE> % mv /usr/apps/sbin/httpd_perl/httpd /usr/apps/sbin/httpd_perl/httpd_perl
</PRE>
<P>
now update the apachectl utility 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>
Now proceed to <A HREF="././config.html#">Server Configuration</A> section.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Is_it_possible_to_install_mod_pe">Is it possible to install mod_perl without root access?</A></H1></CENTER>
<P>
Yes, no problem with that. Follow the instructions above and when you
encounter APACI_ARGS use your home directory or alike as a prefix (e.g
<CODE>/home/stas/www</CODE>) and everything will be installed there. There is a chance that some perl
libs will be not installed on your server by root and you will have to
install these locally too. See the <A
HREF="http://www.esafe.com/stas/TULARC/webmaster/myfaq.html#7">http://www.esafe.com/stas/TULARC/webmaster/myfaq.html#7</A>
for more information on local perl installations.
<P>
You will not be able to set the server to listen to port lower then 1024
(if you aren't a root). So pick your port as a number above the 1024. (I
use 8080 in most cases). Note that you will have to use the <A
HREF="http://www.you.com:8080">http://www.you.com:8080</A> in that case.
But it's not a problem since generally users don't access directly the cgi
but from the webpage, so they shouldn't know at all that the port is
different.
<P>
You will need to worry to put the start server script into rc.d directory
of your machine, so if the last will be rebooted - your webserver will be
restarted automatically.
<P>
One more important thing is Resources, mod_perl is very memory greedy and
if you will run lots of mod_perl processes on that machine, most likely
your host will ask you to shutdown the mod_perl server, or to find another
home. You have a few solutions: <STRONG>a.</STRONG> reduce resource usage - see <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A> <STRONG>b.</STRONG> ask your ISP if you can put a dedicated machine into their computer room
and be root there. <STRONG>c.</STRONG> look for another ISP with lots of resources or one that supports mod_perl
(not likely)
<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/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Server 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>
Server 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>
<LI><A HREF="#aliases_configurations">aliases configurations</A>
</UL>
<LI><A HREF="#Configuration_of_Location">Configuration of Location</A>
<UL>
<LI><A HREF="#perl_status_location">perl-status location </A>
<LI><A HREF="#perl_startup_file">perl-startup file</A>
<LI><A HREF="#PerlFreshRestart">PerlFreshRestart</A>
<LI><A HREF="#What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A>
<LI><A HREF="#Is_it_possible_to_preopen_a_DB_c">Is it possible to preopen a DB connection at the server startup?</A>
<LI><A HREF="#Perl_behavior_controls">Perl behavior controls</A>
</UL>
<LI><A HREF="#Perl_Sections">Perl Sections</A>
<LI><A HREF="#General_pitfalls">General pitfalls</A>
<UL>
<LI><A HREF="#My_cgi_perl_code_is_being_return">My cgi/perl code is being returned as a plain text instead of being executed by the webserver?</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="configuration">configuration</A></H1></CENTER>
<P>
You have just installed the new apache/mod_perl server. Now you have to
configure server's configuration files. To learn how to configure the
apache's config files, please the use the apache's documentation or just
open the files in conf directory and follow the instructions in these files
- they are self explainable...
<P>
Before you start configuration of mod_perl, configure the apache, and see
that it works. When done, come back to continue...
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="aliases_configurations">aliases configurations</A></H2></CENTER>
<P>
OK, first thing you will want to specify the location from where all
mod_perl scripts will be called.
<P>
in srm.conf add:
<P>
<PRE> # plain cgi-bin:
ScriptAlias /cgi-bin/ /usr/apps/myproject/cgi-bin
# Apache::Registry mode
ScriptAlias /perl/ /usr/apps/myproject/cgi/
</PRE>
<P>
<PRE> # Apache::PerlRun mode
ScriptAlias /cgi-perl/ /usr/apps/myproject/cgi/
</PRE>
<P>
Alias allows the server to locate the script that was called at the
filesystem.
<P>
Alias is the start of the URL path to the script you call, like when you
fetch <A
HREF="http://www.you.com/perl/test.pl">http://www.you.com/perl/test.pl</A>
, server will look for the file test.pl at /usr/apps/myproject/cgi but
execute it as a Apache::Registry script, after you set this (see the next
section). <A
HREF="http://www.you.com/perl/test.pl">http://www.you.com/perl/test.pl</A>
will be mapped to /usr/apps/myproject/cgi-bin/test.pl . Basically you can
have all your cgis located at the same place at filesystem, and to call the
same script in any of 3 modes by just replacing the first directory of the
URL (cgi-bin|perl|cgi-perl) - Isn't that cool? If something is going wrong
with your mod_perl you can easily call the scripts in the mod_cgi mode
without changing the script (in most cases) but only the URL to call it,
and then to put it back!!!
<P>
Of course you can choose any other alias (you will use it later in
http.conf), you can choose to use all 3 modes or only one of these (It's
unlikely to run plain cgi-bin scripts from mod_perl server - the price is
too high, you better run these at plain apache server. See
<A HREF="././scenario.html#Making_a_strategic_decision">Real World scenario</A> for details)
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Configuration_of_Location">Configuration of Location</A></H1></CENTER>
<P>
Now we work with httpd.conf, I add all the mod_perl stuff at the end of
file, after the native apache configurations finish.
<P>
First we add:
<P>
<PRE> <Location /perl>
#AllowOverride None
SetHandler perl-script
PerlHandler Apache::Registry
Options ExecCGI
allow from all
PerlSendHeader On
</Location>
</PRE>
<P>
This location's configuration makes all scripts that has been called with
/perl path at the beginning to be executed under
<STRONG>Apache::Registry</STRONG> module and as cgi (so the <CODE>ExecCGI</CODE>, if you omit this option the script will be just printed to the caller's
browser as a plain text or will trigger the 'Save-As' window).
<P>
<CODE>PerlSendHeader On</CODE> tells the server to send an HTTP header to the browser, on every script
invocation. You will want to turn it off for you nph (non-parsed-headers)
scripts.
<P>
Remember the Alias from the section above? We must use the same Alias here,
if you use Location that doesn't have the same Alias defined in srm.conf,
the server will fail to locate the script at the filesystem. I'm talking
about scripts execution (There are cases where Location is something that's
being executed by the server itself, without having the corresponding file,
like <A HREF="#perl_status">perl-status</A>)
<P>
Note that sometimes you will have to to add : PerlModule Apache::Registry
<P>
before you specify the location that uses Apache::Registry as a
PerlHandler. Basically you can start running the scripts in the
Apache::Registry mode...
<P>
You have to do nothing about /cgi-bin (mod_cgi), since it has nothing to do
with mod_perl
<P>
A similar location configuration for Apache::PerlRun. (More about
<A HREF="././porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun</A>)
<P>
<PRE> <Location /cgi-perl>
#AllowOverride None
SetHandler perl-script
PerlHandler Apache::PerlRun
Options ExecCGI
allow from all
PerlSendHeader On
</Location>
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="perl_status_location">perl-status location</A></H2></CENTER>
<P>
/perl-status location allows you to see many things about your server. See
/<A HREF="././status.html#Configuration">perl-status</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="perl_startup_file">perl-startup file</A></H2></CENTER>
<P>
Since many times you have to add many perl directives to the config file,
it can be a good idea to put all of these into one file, so the config file
will be cleaner, also you can call <CODE>perl -c perl-startup</CODE>
to test the file's syntax. What is takes? Add this line to httpd.conf:
<P>
<PRE> # startup.perl loads all functions that we want to use within mod_perl
Perlrequire /path/to/startup.pl
</PRE>
<P>
An example of perl-startup file:
<P>
<PRE> 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 "GATEWAY_INTERFACE not Perl!";
# for things in the "/perl" URL
use Apache::Registry;
#load perl modules of your choice here
#this code is interpreted *once* when the server starts
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');
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="PerlFreshRestart">PerlFreshRestart</A></H2></CENTER>
<P>
To reload <CODE>PerlRequire</CODE>, <CODE>PerlModule</CODE>, other <CODE>use()'d</CODE> modules and flush the Apache::Registry cache
on server restart, add:
<P>
<PRE> PerlFreshRestart On
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A></H2></CENTER>
<P>
Modules that are being loaded at the server startup will be shared among
server children, so only one copy of each module will be loaded, thus
saving a lot of RAM for you.
<P>
See <A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Is_it_possible_to_preopen_a_DB_c">Is it possible to preopen a DB connection at the server startup?</A></H2></CENTER>
<P>
Yes! See <A HREF="././performance.html#Persistent_DB_Connections">Persistent DB Connections</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Perl_behavior_controls">Perl behavior controls</A></H2></CENTER>
<P>
For <CODE>PerlWarn</CODE> and <CODE>PerlTaintCheck</CODE> see <A HREF="././porting.html#Switches_w_T">Switches -w, -T</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Perl_Sections">Perl Sections</A></H1></CENTER>
<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>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="General_pitfalls">General pitfalls</A></H1></CENTER>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="My_cgi_perl_code_is_being_return">My cgi/perl code is being returned as a plain text instead of being executed by the webserver?</A></H2></CENTER>
<P>
Check your config files and make sure that the ``ExecCGI'' is turned on in
your configurations.
<P>
<PRE> <Location /perl>
SetHandler perl-script
PerlHandler Apache::Registry
Options ExecCGI
allow from all
PerlSendHeader On
</Location>
</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 12/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Server Controlling and Monitoring</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>
Server Controlling and Monitoring</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="#Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</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 exact 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 script is 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="Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A></H1></CENTER>
<P>
With mod_perl many things can happen to your server. The worse one is the
possibility that the server will die when you will be not around. As with
any other critical service you need to run some kind of watchdog.
<P>
One simple solution is to use a slightly modified apachectl script which I
called apache.watchdog and to put it into the crontab to be called every 30
minutes or even every minute - if it's so critical to make sure the server
will be up all the time.
<P>
Crontab entry:
<P>
0,30 * * * * /path/to/the/apache.watchdog >/dev/null 2>&1
<P>
The script:
<P>
<PRE> #!/bin/sh
# this script is a watchdog to see whether the server is online
# It tries to restart the server if it's down and sends an email alert to admin
# admin's email
EMAIL=webmaster@somewhere.far
#EMAIL=root@localhost
# the path to your PID file
PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid
# the path to your httpd binary, including options if necessary
HTTPD=/usr/apps/sbin/httpd_perl/httpd_perl
# check for pidfile
if [ -f $PIDFILE ] ; then
PID=`cat $PIDFILE`
</PRE>
<P>
<PRE> if kill -0 $PID; then
STATUS="httpd (pid $PID) running"
RUNNING=1
else
STATUS="httpd (pid $PID?) not running"
RUNNING=0
fi
else
STATUS="httpd (no pid file) not running"
RUNNING=0
fi
if [ $RUNNING -eq 0 ]; then
echo "$0 $ARG: httpd not running, trying to start"
if $HTTPD ; then
echo "$0 $ARG: httpd started"
mail $EMAIL -s "$0 $ARG: httpd started" </dev/null >& /dev/null
else
echo "$0 $ARG: httpd could not be started"
mail $EMAIL -s "$0 $ARG: httpd could not be started" </dev/null >& /dev/null
fi
fi
</PRE>
<P>
Another approach, probably even more practical, is to use the Cool LWP perl
package , to test the server by trying to fetch some document (script)
served by the server. Why is it more practical? Since the while server can
be up as a process, it can be stuck and not working (SYN_RECV state -
anyone???), So failing to get the document will trigger restart, and
``probably'' the problem will go away. (Just replace <CODE>start</CODE> with <CODE>restart</CODE> in the <CODE>$restart_command</CODE> below.
<P>
Again we put this script into a crontab to call it every 30 minutes.
<P>
<PRE> #!/usr/local/bin/perl -w
use strict;
use diagnostics;
use URI::URL;
use LWP::MediaTypes qw(media_suffix);
my $VERSION = '0.01';
use vars qw($ua $proxy);
require LWP::UserAgent;
use <A HREF="HTTP::Status">HTTP::Status</A>;
###### Config ########
my $test_script_url = "<A HREF="http://www.stas.com:81/perl/test.pl"">http://www.stas.com:81/perl/test.pl"</A>;;
my $monitor_email = 'root@localhost';
my $restart_command = '/usr/apps/sbin/httpd_perl/apachectl start';
my $mail_program = "/usr/lib/sendmail -t -n";
######################
$ua = new LWP::UserAgent;
$ua->agent("$0/Stas " . $ua->agent);
# Uncomment the proxy if you don't use it!
# $proxy="<A HREF="http://www-proxy.com"">http://www-proxy.com"</A>;;
$ua->proxy('http', $proxy) if $proxy;
# If returns '1' it's we are alive
exit 1 if checkurl($test_script_url);
# We have got the problem - the server seems to be down. Try to
# restart it.
my $status = system $restart_command;
# print "Status $status\n";
my $message = ($status == 0)
? "Server was down and successfully restarted!"
: "Server is down. Can't restart.";
</PRE>
<P>
<PRE> my $subject = ($status == 0)
? "Attention! Webserver restarted"
: "Attention! Webserver is down. can't restart";
</PRE>
<P>
<PRE> # email the monitoring person
my $to = $monitor_email;
my $from = $monitor_email;
send_mail($from,$to,$subject,$message);
</PRE>
<P>
<PRE> # input: URL to check
# output: 1 if success, o for fail
#######################
sub checkurl{
my ($url) = @_;
# Fetch document
my $res = $ua->request(<A HREF="HTTP::Request->">HTTP::Request-></A>;new(GET => $url));
# Check the result status
return 1 if is_success($res->code);
# failed
return 0;
} # end of sub checkurl
# sends email about the problem
#######################
sub send_mail{
my($from,$to,$subject,$messagebody) = @_;
</PRE>
<P>
<PRE> open MAIL, "|$mail_program" or die "Can't open a pipe to a $mail_program :$!\n";
print MAIL <<__END_OF_MAIL__;
To: $to
From: $from
Subject: $subject
$messagebody
__END_OF_MAIL__
close MAIL;
}
</PRE>
<P>
<PRE> <META>
Is it possible to make the server do something when it dies? e.g
restart itself :) NO, really when it dies , (killed in improper way?)
is it possible to trigger some action?
</PRE>
<P>
<PRE> Ideas?
</META>
</PRE>
<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 concurrently 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 achieved with this technique is: A full control over
start/stop, number of children, 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>
Of course 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>
Of course you have another problem: The cgi generates some html, which
should be called again. If it generates a URL with hard coded 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 transparent 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 start off 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 paths 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
completely 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 web server 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 invoke 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 off topic 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 12/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: CGI => mod_perl Porting. mod_perl Coding guidelines.</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>
CGI => mod_perl Porting. mod_perl Coding guidelines.</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_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) 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="#diagnostics_pragma">diagnostics pragma</A>
<LI><A HREF="#Global_Variables">Global Variables</A>
<LI><A HREF="#Code_has_been_changed_but_seems">Code has been changed, but seems that script uses the old code</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>
<LI><A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</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 existent 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 avoid 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. <A
HREF="http://world.std.com/~swmcd/steven/perl/module_mechanics.html">http://world.std.com/~swmcd/steven/perl/module_mechanics.html</A>
<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 paths
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! (Of course 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>
<STRONG>Note</STRONG> that if you run the script under Apache::Registry, <STRONG>The Apache
function `exit' overrides the Perl core built-in function</STRONG>. While you see the <CODE>exit()</CODE> listed in <CODE>@EXPORT_OK</CODE>
of Apache package, Apache::Registry makes something you don't see and
imports this function for you.
<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_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H3></CENTER>
<P>
To run a Non Parsed Header CGI script under mod_perl, simply add to your
code:
<P>
<PRE> local $| = 1;
</PRE>
<P>
And 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 equivalent special variable. For example, the $^W
variable corresponds to the -w switch. Consult perlvar for more details.
With mod_perl it is also possible to turn on warnings globally 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="diagnostics_pragma">diagnostics pragma</A></H2></CENTER>
<P>
Perl compiler pragma to force verbose warning diagnostics. Put at the start
of your scripts:
<P>
<PRE> use diagnostics;
</PRE>
<P>
This pragma turns on the -w mode, but gives you a much better diagnostics
of the errors and warnings. Generally it explains the reason for
warnings/errors you get, shows you an example of code, where the same kind
of warning is being triggered and tells you the remedy.
<P>
It's a bad idea to keep it in your production code! Since it'll spit
zillions of diagnostics lines into your error_log file. And it'll add
significant overhead to the cgi's runtime. (I discovered this by using
Devel::DProf!)
<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_has_been_changed_but_seems">Code has been changed, but seems that script uses the old code</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
exactly by that size. Now if you have 20 children 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 of course. Try to process line at a time and print it back to the
file (if you need to modify the file itself, use temporary 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 has grew up 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 possible to update)....
<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 allocated for the records that matched the query.
(Again remember to multiply it by the number of the children 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 or 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 behavior:
# 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 invocation 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 voila 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
successfully 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). Of course the example is too trivial - but
believe me it happens!
<P>
Just another little one liner 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 regexp 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 regexp 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 regexp
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>
</PRE>
<P>
See <A HREF="#">Apache::PerlRun - a closer look</A>
<P>
Another ``bad'', but working method is to set MaxRequestsPerChild to 1,
which will force each child to exit after serving only 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 spawn more servers ahead so the killed one will be immediately
replaced with the fresh one. Again, probably that's not what you want.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A></H2></CENTER>
<P>
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 any change. Unlike
Apache::Registry, the Apache::PerlRun handler does not cache the script
inside of a subroutine. Scripts will be ``compiled'' on each request. After
the script has run, it's namespace is flushed of all variables and
subroutines. Still, you don't have the overhead of loading the perl and
compilation time of the standard modules (If your script is very light, but
uses lots of standard modules - you will see no difference between
Apache::PerlRun and Apache::Registry !).
<P>
Be aware though, that if you use some packages that use internals variables
that has circular references, they will be not flushed!!!
<P>
Apache::PerlRun only flushes your script's namespace, which does not
include any other required package's namespace. If there's a reference to
<CODE>my()</CODE> scoped variable that's keeping it from being DESTROYed
after leaving the eval scope (of Apache::PerlRun), that cleanup might not
be taken care of until the server is shutdown and
<CODE>perl_destruct()</CODE> is run, which always happens after running
command line scripts. Consider this example:
<P>
<PRE> package Foo;
sub new { bless {} }
sub DESTROY {
warn "Foo->DESTROY\n";
}
</PRE>
<P>
<PRE> eval <<'EOF';
package my_script;
my $self = Foo->new;
#$self->{circle} = $self;
EOF
</PRE>
<P>
<PRE> print $@ if $@;
print "Done with script\n";
</PRE>
<P>
First you'll see:
<P>
<PRE> Foo->DESTROY
Done with script
</PRE>
<P>
Then, uncomment the line where <CODE>$self</CODE> makes a circular
reference, and you'll see:
<P>
<PRE> Done with script
Foo->DESTROY
</PRE>
<P>
In this case, under mod_perl you wouldn't see 'Foo->DESTROY' until the
server shutdown, or your module properly took care of things.
<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/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!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
<CODE>&x</CODE> 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
<CODE>&y</CODE> is called only from inside &x.
<P>
(this was partially 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 obvious. 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>
Also see the clarification of <CODE>my()</CODE> vs. <CODE>use vars</CODE> - Ken Williams writes:
<P>
<PRE> Yes, there's quite a bit of difference! With use vars(), you're
making an entry in the symbol table, and you're telling the compiler
that you're going to be referencing that entry without an explicit
package name.
</PRE>
<P>
<PRE> With my(), NO ENTRY IS PUT IN THE SYMBOL TABLE. The compiler figures
out _at_ _compile_time_ which my() variables (i.e. lexical variables)
are the same as each other, and once you hit execute time you can't go
looking those variables up in the symbol table.
</PRE>
<P>
And <CODE>my()</CODE> vs. <CODE>local()</CODE> - Randal Schwartz writes:
<P>
<PRE> local() creates a temporal-limited package-based scalar, array, hash,
or glob -- when the scope of definition is exited at runtime, the
previous value (if any) is restored. References to such a variable
are *also* global... only the value changes. (Aside: that's what
causes variable suicide. :)
</PRE>
<P>
<PRE> my() creates a lexically-limited non-package-based scalar, array, or
hash -- when the scope of definition is exited at compile-time, the
variable ceases to be accessible. Any references to such a variable
at runtime turn into unique anonymous variables on each scope exit.
</PRE>
<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 immediately 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 millisecs 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 require 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 guarantee 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]$/; # guaranteed if meta-characters present
</PRE>
<P>
Phil. Chu contributed this:
<P>
It depends on the complexity of the regexp you apply this technique to. One
common usage where compiled regexp is usually more efficient is to ``match
any one of a group of patterns'' over and over again.
<P>
Maybe with some helper routine, it's easier to remember. Here is one
slightly modified from Jeffery Friedl's example in his book ``Mastering
Regex.''. I find it quite useful:
<P>
<PRE> #####################################################
# Build_MatchMany_Function
# -- Input: list of patterns
# -- Output: A code ref which matches its $_[0]
# against ANY of the patterns given in the
# "Input", efficiently.
#
sub Build_MatchMany_Function {
my @R = @_;
my $expr = join '||', map { "\$_[0] =~ m/\$R[$_]/o" } ( 0..$#R );
my $matchsub = eval "sub { $expr }";
die "Failed in building regex @R: $@" if $@;
$matchsub;
}
</PRE>
<P>
Example usage:
<P>
<PRE> @some_browsers = qw(Mozilla Lynx MSIE AmigaVoyager lwp libwww);
$Known_Browser=Build_MatchMany_Function(@some_browsers);
</PRE>
<P>
<PRE> while (<ACCESS_LOG>) {
# ...
$browser = get_browser_field($_);
if ( ! &$Known_Browser($browser) ) {
print STDERR "Unknown Browser: $browser\n";
}
# ...
}
</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 (if you have such - The less you have them the better, but
sometimes you just can't without them). It's hard to test with multiply
servers serving your cgi since each child 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>
<PRE> use vars qw($num);
$num ||= random();
print ++$num;
</PRE>
<P>
This script initializes the <CODE>$num</CODE> with random value, then it
increments on each request and print it out. Running this script in
multiply server environment will result in something like 1,9,4,19 (number
per reload), since ``each'' time your script will be served by a different
child. (On some OSes parent process assign all the requests to the same
child process if all of the children are idle... AIX...). But if you run in
httpd -X single server mode you will get 2,3,4,5... (taken that the
<CODE>random()</CODE> returned 1 at the first call)
<P>
But don't get too obsessive with this mode, since working only in single
server mode sometimes hides problems that show up when you switch to multi
server 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 multi server 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 children 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 behavior 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 12/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Warnings and Errors: Where and Why.</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: Where and Why.</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="#A_general_advice">A general advice </A>
<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="A_general_advice">A general advice</A></H1></CENTER>
<P>
Using the <CODE>use diagnostics;</CODE> generally helps you to determine the source of the problem and how to solve
it. See <A HREF="././porting.html#diagnostics_pragma">diagnostics pragma</A> for more info.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></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>
<PRE> <META>
Someone said:
You won't see that warning in this case with 5.004_05 or 5.005+.
</PRE>
<P>
<PRE> I'm running perl5.00502 and I still get these warnings???
</PRE>
<P>
<PRE> Who is right?
</META>
</PRE>
<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/foo/cgi/tmp.pl line 4.
eval 'package Apache::ROOT::perl::tmp_2epl;use Apache qw(exit);sub handler {
#line 1 /usr/apps/foo/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/foo/cgi/tmp.pl line 4
eval {...} called at /usr/apps/foo/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. When you use <CODE>use strict;</CODE> pragma (and you better do that), all variables should be defined before
being used.
<P>
The bad thing is that sometimes the whole script that can be of thousands
lines is being printed to error_log file as a code that the server has
tried to <CODE>eval()uate.</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>
<PRE> Can't undef active subroutine at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 102.
Called from package Apache::Registry, filename /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm, line 102
</PRE>
<P>
This problem is caused when, a client drops the connection while httpd is
in the middle of a write, httpd timeout happens, sending a SIGPIPE, and
Perl in that child is stuck in the middle of it's eval context. This is
fixed by the Apache::SIG module which is called by default. This should not
happen unless you have code that is messing with $SIG{PIPE}. It's also
triggered only when you've changed your script on disk and mod_perl is
trying to reload it.
<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 every time 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 12/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Performance. Benchmarks.</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>
Performance. Benchmarks.</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="#Preopen_DB_connection_at_server_">Preopen DB connection 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_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A>
<UL>
<LI><A HREF="#Developers_Talk">Developers Talk</A>
<LI><A HREF="#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A>
<LI><A HREF="#Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A>
<LI><A HREF="#PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A>
</UL>
<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>
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="Preopen_DB_connection_at_server_">Preopen DB connection at server startup</A></H1></CENTER>
<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="#Persistent_DB_Connections">Persistant DB Connections</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_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A></H1></CENTER>
<P>
How much faster is mod_perl that CGI? There are many ways to benchmark the
two. See a few examples and numbers below, also checkout the benchmark/
directory of mod_perl dist for more examples.
<P>
If you write a benchmarks from your own for heavy scripts use
<CODE>Benchmark</CODE> and for very fast scripts use <CODE>Time::HiRes</CODE> modules.
<P>
There is no need to write a special benchmark, if you want to impress your
boss or colleagues, just take the heaviest cgi script you have, open 2
xterms and call the same script in mod_perl mode in one xterm and in
mod_cgi mode in the other. You can use lwp-get from LWP package to emulate
the web agent (browser). (benchmark/ directory of mod_perl dist includes
such an example)
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Developers_Talk">Developers Talk</A></H2></CENTER>
<P>
Perrin Harkins writes on benchmarks or comparisons, official or unofficial:
<BLOCKQUOTE>
<P>
I have used some of the platforms you mentioned and researched others. What
I can tell you for sure, is that no commercially available system offers
the depth, power, and ease of use that mod_perl has. Either they don't let
you access the web server internals, or they make you use less productive
languages than Perl, sometimes forcing you into restrictive and confusing
APIs and/or GUI development environments. None of them offer the level of
support available from simply posting a message to this list, at any price.
<P>
As for performance, beyond doing several important things (code-caching,
pre-forking/threading, and persistent database connections) there isn't
much these tools can do, and it's mostly in your hands as the developer to
see that the things which really take the time (like database queries) are
optimized.
<P>
The downside of all this is that most manager types seem to be unable to
believe that web development software available for free could be better
than the stuff that cost $25,000 per CPU. This appears to be the major
reason most of the web tools companies are still in business. They send a
bunch of suits to give PowerPoint presentations and hand out glossy
literature to your boss, and you end up with an expensive disaster and an
approaching deadline.
<P>
But I'm not bitter or anything...
</BLOCKQUOTE>
<P>
Jonathan Peterson adds:
<BLOCKQUOTE>
<P>
Most of the major solutions have something that they do better than the
others, and each of them has faults. Microsofts ASP has a very nice objects
model, and has IMO the best data access object (better than DBI to use -
but less portable) It has the worst scripting language. PHP has many of the
advantages of Perl-based solutions, but is less complicated for developers.
Netscape's Livewire has a good object model too, and provides good
server-side Java integration - if you want to leverage Java skills, it's
good. Also, it has a compiled scripting language - which is great if you
aren't selling your clients the source code (and a pain otherwise).
<P>
mod_perl's advantage is that it is the most powerful. It offers the
createst degree of control with one of the more powerful languages. It also
offers the greatest granularity. You can use an embedding module (eg eperl)
from one place, a session module (Session) from another, and your data
acces module from yet another.
<P>
I think the Apache::ASP module looks very promising. It has very easy to
use and adequately powerful state maintenance, a good embedding system, and
a sensible object model (that emulates the Microsoft ASP one). It doesn't
replicate MS's ADO for data access, but DBI is fine for that.
<P>
I have always found that the developers available make the greatest impact
on the decision. If you have a team with no Perl experience, and a small or
medium task, using something like PHP, or Microsoft ASP, makes more sense
than driving your staff into the vertical learning curve they'll need to
use mod_perl.
<P>
For very large jobs, it may be worth finding the best technical solution,
and then recruiting the team with the necessary skills.
</BLOCKQUOTE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A></H2></CENTER>
<P>
Here are the numbers from Michael Parker's mod_perl presentation at Perl
Conference (Aug, 98) <A
HREF="http://www.realtime.net/~parkerm/perl/conf98/index.htm">http://www.realtime.net/~parkerm/perl/conf98/index.htm</A>
. The script is a standard hits counter, but it logs the counts into the
mysql relational DataBase:
<P>
<PRE> Benchmark: timing 100 iterations of cgi, perl... [rate 1:28]
</PRE>
<P>
<PRE> cgi: 56 secs ( 0.33 usr 0.28 sys = 0.61 cpu)
perl: 2 secs ( 0.31 usr 0.27 sys = 0.58 cpu)
Benchmark: timing 1000 iterations of cgi,perl... [rate 1:21]
</PRE>
<P>
<PRE> cgi: 567 secs ( 3.27 usr 2.83 sys = 6.10 cpu)
perl: 26 secs ( 3.11 usr 2.53 sys = 5.64 cpu)
Benchmark: timing 10000 iterations of cgi, perl [rate 1:21]
</PRE>
<P>
<PRE> cgi: 6494 secs (34.87 usr 26.68 sys = 61.55 cpu)
perl: 299 secs (32.51 usr 23.98 sys = 56.49 cpu)
</PRE>
<P>
We don't know what server configurations was used for these testing, but I
guess the numbers talks for themselves.
<P>
The source code of the script at <A
HREF="http://www.realtime.net/~parkerm/perl/conf98/sld006.htm">http://www.realtime.net/~parkerm/perl/conf98/sld006.htm</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A></H2></CENTER>
<P>
As noted before for very fast scripts you will have to use Time::HiRes
module, it's usage is similar to the Benchmark's.
<P>
<PRE> use Time::HiRes qw(gettimeofday tv_interval);
my $start_time = [ gettimeofday ];
&sub_that_takes_a_teeny_bit_of_time()
my $end_time = [ gettimeofday ];
my $elapsed = tv_interval($start_time,$end_time);
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><H2><A NAME="PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A></H2></CENTER>
<P>
At <A
HREF="http://perl.apache.org/dist/contrib/">http://perl.apache.org/dist/contrib/</A>
you will find Apache::Timeit package which does PerlHandler's Benchmarking.
<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 persistence 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 careful 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:
<P>
<PRE> httpd.conf
----------
PerlModule Apache::DBI
It is important, to load this module before any other ApacheDBI module !
</PRE>
<P>
<PRE> a script.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 requirements 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>
Also some folks at list suggested to change the timeout of the server (they
talked specifically about mysql). So starting from 3.22.x you can set a
wait_timeout option at mysqld server startup to change the default value,
setting it to 24 hours probably will fix the timeout problem.
<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):
<P>
<PRE> USER PID %CPU %MEM 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
</PRE>
<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>
--------------------------------------------------------------------------------
<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>
--------------------------------------------------------------------------------
<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>
<PRE> % setenv PERL5OPT -d:DProf
% httpd -X -d `pwd` &
... make some requests to the server here ...
% kill `cat logs/httpd.pid`
% unsetenv PERL5OPT
% dprofpp
</PRE>
<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 12/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: mod_perl Status. Peeking into the Server's Perl 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>
mod_perl Status. Peeking into the Server's Perl 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>
<LI><A HREF="#Configuration">Configuration</A>
<LI><A HREF="#Usage">Usage</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="Watching_the_server">Watching the server</A></H1></CENTER>
<P>
Very useful feature. You can watch what happens to the perl parts of the
server. Below you will find the instructions of configuration and usage of
this feature
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Configuration">Configuration</A></H2></CENTER>
<P>
Add this to http.conf:
<P>
<PRE> <Location /perl-status>
SetHandler perl-script
PerlHandler Apache::Status
order deny,allow
#deny from all
#allow from
</Location>
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Usage">Usage</A></H2></CENTER>
<P>
Assuming that your mod_perl server listens to port 81, 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>
Below all sections should be links:
<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 12/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: Code 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>
Code 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="#Sometimes_script_works_Sometime">Sometimes script works, Sometimes Not</A>
<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="Sometimes_script_works_Sometime">Sometimes script works, Sometimes Not</A></H1></CENTER>
<P>
See <A HREF="././porting.html#Sometimes_it_works_Sometimes_Not">Sometimes it works Sometimes Not</A>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></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, interpreter 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 12/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!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 behavior by setting in config file:
<P>
<PRE> PerlSendHeader On
</PRE>
<P>
The safest bet is to use CGI.pm's <CODE>print header();</CODE> method (If you use this, you don't need the above setting)
<P>
Also there is $ENV{PERL_SEND_HEADER} to see if PerlSendHeader is On or Off.
<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/07/98
</FONT>
</B>
</TD>
<TD>
<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>mod_perl guide: </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. 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>The Apache/Perl mailing list (modperl@apache.org) <B>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 <a
href="mailto:majordomo@apache.org">majordomo@apache.org</a> with the
string "subscribe modperl" in the body. </P>
<P><B>Searchable </B>mod_perl mailing list<A
HREF="http://forum.swarthmore.edu/epigone/modperl"><B>archive</B></A>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 12/04/1998 </FONT></B></TD>
<TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" BORDER=0 ALT="Mod Perl Icon" HEIGHT=59 WIDTH=150></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>
<HR SIZE=6>