ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


HTTP Wrangler

Installing mod_perl from RPM

by Stephen Figgins
03/17/2000

mod_perl uses the Apache API to embed a complete Perl interpreter into your web server. This not only speeds up your CGI programs, it makes almost all of the Apache API available to the Perl programmer. Red Hat has a mod_perl RPM you can easily install. Configuring it is trickier.

Here's a glossary to help define some of the terms used in this article.

Using RPMs like a city slicker

A package manager is a great tool for keeping track of what is installed on your system. All the files for an application or set of tools are put together in packages that can be installed, removed, upgraded, or queried. One of the most popular package managers is the Red Hat Package Manager. Packages for the Red Hat Package Manager are often called RPMs.

Some wranglers are picky about RPMs. They don't like the idea that someone else is making decisions for them. Because these packages have been precompiled, users do not have complete control over all options. But I don't always need control over how a program is configured -- I like being able to quickly install, uninstall, or upgrade all the files associated with a program. Maybe I am more of a city slicker than a wrangler.

Good instructions on how to install from source can be found in the book Writing Apache Modules with Perl and C, but if you want to install from an RPM Look for the mod_perl RPM on your CD-ROM drive and use rpm -Uvh to install mod_perl from that file. On my RedHat 6.1 system I ran:

# rpm -Uvh /mnt/cdrom/RedHat/RPMS/mod_perl-1.21-2.i386.rpm
mod_perl           ##################################################
#

I like RPMs because they are usually this easy. I install it with the package manager and it works. But the mod_perl RPM was a bit trickier. I still needed to configure it. Here is what you do to configure Apache to use mod_perl for CGI programs and to run a test module (Hello.pm)written for the Apache API.

Let Apache know about the new module.

The mod_perl RPM is compiled as a Dynamic Shared Object (DSO). Before DSOs came along you had to recompile the server every time you wanted to take advantage of a new module. But with DSOs, Apache can load new modules dynamically. Red Hat has compiled Apache to use a DSO. The mod_perl module has been compiled as a DSO. All you need do to get Apache to load the module is edit your httpd.conf file to tell Apache to load it.

Configuration files for Apache are generally kept in a directory called conf found under the Apache server root. For Red Hat, the server root is /etc/httpd. It is important to know what the server root is because many of the directives you will use in the configuration file are server root relative.

Add these lines to httpd.conf in /etc/httpd/conf/httpd.conf:

LoadModule perl_module        modules/libperl.so
AddModule mod_perl.c

If you are using Red Hat, these should already be in your httpd.conf file and just need to be uncommented.

Create a place for Perl configuration information.

To keep things tidy, add these lines to your httpd.conf file:

<IfModule mod_perl.c>
  Include conf/perl.conf
</IfModule>

While you could put all your Perl directives in httpd.conf, this will keep your main configuration file a little less cluttered. The Include directive here is server root relative which is why we did not have to say /etc/httpd/conf/perl.conf. We will put information in this file later.

Create a startup file for the Perl interpreter.

When the Perl interpreter starts up it is useful to tell it a few things, such as where your module files can be found or to load up a few files you plan on using a lot. Here is an example of a startup file taken from the book Writing Apache Modules with Perl and C:

#!/usr/bin/perl
# startup.pl - Called each time Apache is launched or restarted.
# Sets environment variables and preloads commonly used modules.

# modify the include path before we do anything else
Begin {
  use Apache ();
  use lib Apache->server_root_relative('lib/perl');
}
# commonly used modules
use Apache::Registry ()
use Apache::Constants ()
use CGI qw(-compile :all);
use CGI::Carp ();
1;

The server_root_relative method appends the string we gave "lib/perl" to the server root "etc/httpd." So Perl reads this as:

  use lib '/etc/httpd/lib/perl';

It adds this directory to the @INC array, the list of directories Perl searches when it goes looking for a module. Save this startup.pl file in your /etc/httpd/conf directory and make it executable.

# chmod +x startup.pl

To tell Apache to load the startup file, put these lines at the beginning of your perl.conf file:

PerlRequire        conf/startup.pl
PerlFreshRestart        On

Create a fast CGI directory for your Perl CGI programs.

The embedded interpreter can significantly speed up your existing CGI programs. Make a place to put these files by creating a perl directory. On Red Hat I did this:

# mkdir /home/httpd/perl

Now, let Apache know about the directory by adding this to your srm.conf file:

Alias /perl/ /home/httpd/perl/
<Location /perl>
  SetHandler perl-script
    PerlHandler Apache::Registry
	Options +ExecCGI
</Location>

If you are using Red Hat, these should already be in your srm.conf file and you will just need to uncomment them. This tells Apache to handle Perl scripts with the Apache::Registry module. Apache::Registry will load and run the script, and keep it in memory, so the next time it is requested it will run even faster. This should work for almost all your existing Perl CGI scripts.

Because the script does not go away after execution, scripts that rely on global variables without initializing them first, or depend on the process ID of the script to be different each time you run it, will break. If you have a lot of scripts that do that, consider using Apache::PerlRun instead of Apache::Registry. You will get the speed of the embedded interpreter, but the script won't stay in memory.

Tell Apache where to find the Hello module.

I have taken the Apache/Hello.pm module directly from the book Writing Apache Modules with Perl and C. It is described more fully there. Here is the code:

# Hello.pm - an example from Writing Apache Modules
# with Perl and C
package Apache::Hello;

use strict;
use Apache::Constants qw(:common);

sub handler {
    my $r = shift;
    $r->content_type('text/html');
    $r->send_http_header;
    return OK if $r->header_only;
    my $host = $r->get_remote_host;
    $r->print(<<END);
<HTML>
<HEADER>
<TITLE>Hello There</TITLE>
</HEADER>
<BODY>
<H1>Hello $host</H1>
Who would take this book seriously if the first example didn't
say "hello world"?
</BODY>
</HTML>
END
    return OK;
} 

1;
__END__

Save the file as /etc/httpd/lib/perl/Apache/Hello.pm and place these lines in your perl.conf file:

<Location /hello/world>
  SetHandler perl-script
  PerlHandler Apache::Hello
</Location>

Restart the Apache server.

On my Red Hat system, I like to use the initialization script for httpd:

# /etc/rc.d/init.d/httpd restart
Shutting down http:                                      [ OK ]
Starting httpd:                                          [ OK ]
#

Test it out.

You should now be able to load up the Hello.pm module by going to http://localhost/hello/world. Put any new Perl modules that use the Apache API in /etc/httpd/lib/perl/Apache. Also try moving some of your existing CGI code files into the directory /home/httpd/perl/ and running them. You should notice a significant speed increase.

That may have seemed complicated, but those wrangling the source code installation have to make most of these same tweaks after compiling mod_perl. What you lose in control over how Apache and mod_perl were compiled you gain in control over your file system. You can remove or upgrade mod_perl as quickly as roping a calf. You may be using RPMs like a city slicker, but you are still a wrangler. Now get out there and code!


Discuss this article in the O'Reilly Network Apache Forum.

Return to the Apache DevCenter.

 

Copyright © 2009 O'Reilly Media, Inc.