There are situations when you need to install mod_perl-enabled Apache and other components (such as Perl libraries) into nonstandard locations. For example, you might work on a system to which you don't have root access, or you might need to install more than one set of mod_perl-enabled Apache and Perl modules on the same machine (usually when a few developers are using the same server and want to have their setups isolated from each other, or when you want to test a few different setups on the same machine).
We have already seen that you can install mod_perl-enabled Apache into different directories on the system (using the APACHE_PREFIX parameter of Makefile.PL). Until now, all our scenarios have installed the Perl files that are part of the mod_perl package into the same directory as the system Perl files (usually /usr/lib/perl5).
Now we are going to show how can you install both the Apache and the Perl files into a nonstandard directory. We'll show a complete installation example using stas as a username, assuming that /home/stas is the home directory of that user.
Before we proceed, let's look at how to install any Perl module into a nonstandard directory. For an example, let's use the package that includes CGI.pm and a few other CGI::* modules.
First, you have to decide where to install the modules. The simplest approach is to simulate the portion of the / filesystem relevant to Perl under your home directory. Actually, we need only two directories:
/home/stas/bin /home/stas/lib
We don't have to create them, as they are created automatically when the first module is installed. Ninety-nine percent of the files will go into the lib directory. Only occasionally does a module distribution come with Perl scripts that are installed into the bin directory, at which time bin will be created if it doesn't exist.
As usual, download the package from the CPAN repository (CGI.pm-x.xx.tar.gz), unpack it, and chdir to the newly created directory.
Now do a standard perl Makefile.PL to create the Makefile, but this time make use of your nonstandard Perl installation directory instead of the default one:
panic% perl Makefile.PL PREFIX=/home/stas
Specifying PREFIX=/home/stas is the only part of the installation process that is different from usual. Note that if you don't like how Makefile.PL chooses the rest of the directories, or if you are using an older version of it that requires an explicit declaration of all the target directories, you should do this:
panic% perl Makefile.PL PREFIX=/home/stas \ INSTALLPRIVLIB=/home/stas/lib/perl5 \ INSTALLSCRIPT=/home/stas/bin \ INSTALLSITELIB=/home/stas/lib/perl5/site_perl \ INSTALLBIN=/home/stas/bin \ INSTALLMAN1DIR=/home/stas/lib/perl5/man \ INSTALLMAN3DIR=/home/stas/lib/perl5/man3
The rest is as usual:
panic% make panic% make test panic% make install
make install installs all the files in the private repository. Note that all the missing directories are created automatically, so you don't need to create them beforehand. Here is what it does (slightly edited):
Installing /home/stas/lib/perl5/CGI/Cookie.pm Installing /home/stas/lib/perl5/CGI.pm Installing /home/stas/lib/perl5/man3/CGI.3 Installing /home/stas/lib/perl5/man3/CGI::Cookie.3 Writing /home/stas/lib/perl5/auto/CGI/.packlist Appending installation info to /home/stas/lib/perl5/perllocal.pod
If you have to use explicit target parameters instead of a single PREFIX parameter, you will find it useful to create a file called something like ~/.perl_dirs (where ~ is /home/stas in our example), containing:
PREFIX=/home/stas \ INSTALLPRIVLIB=/home/stas/lib/perl5 \ INSTALLSCRIPT=/home/stas/bin \ INSTALLSITELIB=/home/stas/lib/perl5/site_perl \ INSTALLBIN=/home/stas/bin \ INSTALLMAN1DIR=/home/stas/lib/perl5/man \ INSTALLMAN3DIR=/home/stas/lib/perl5/man3
From now on, any time you want to install Perl modules locally, simply execute:
panic% perl Makefile.PL `cat ~/.perl_dirs` panic% make panic% make test panic% make install
Using this technique, you can easily maintain several Perl module repositories. For example, you could have one for production and another for development:
panic% perl Makefile.PL `cat ~/.perl_dirs.production`
or:
panic% perl Makefile.PL `cat ~/.perl_dirs.develop`
Installing Perl modules into nonstandard directories is only half the battle. We also have to let Perl know what these directories are.
Perl modules are generally placed in four main directories. To find these directories, execute:
panic% perl -V
The output contains important information about your Perl installation. At the end you will see:
Characteristics of this binary (from libperl): Built under linux Compiled at Oct 14 2001 17:59:15 @INC: /usr/lib/perl5/5.6.1/i386-linux /usr/lib/perl5/5.6.1 /usr/lib/perl5/site_perl/5.6.1/i386-linux /usr/lib/perl5/site_perl/5.6.1 /usr/lib/perl5/site_perl .
This shows us the content of the Perl special variable @INC, which is used by Perl to look for its modules. It is equivalent to the PATH environment variable, used to find executable programs in Unix shells.
Notice that Perl looks for modules in the . directory too, which stands for the current directory. It's the last entry in the above output.
This example is from Perl Version 5.6.1, installed on our x86 architecture PC running Linux. That's why you see i386-linux and 5.6.1. If your system runs a different version of Perl, or a different operating system, processor, or chipset architecture, then some of the directories will have different names.
All the platform-specific files (such as compiled C files glued to Perl with XS, or some .h header files) are supposed to go into the i386-linux-like directories. Pure Perl modules are stored in the non-platform-specific directories.
As mentioned earlier, you find the exact directories used by your version of Perl by executing perl -V and replacing the global Perl installation's base directory with your home directory. Assuming that we use Perl 5.6.1, in our example the directories are:
/home/stas/lib/perl5/5.6.1/i386-linux /home/stas/lib/perl5/5.6.1 /home/stas/lib/perl5/site_perl/5.6.1/i386-linux /home/stas/lib/perl5/site_perl/5.6.1 /home/stas/lib/perl5/site_perl
There are two ways to tell Perl about the new directories: you can either modify the @INC variable in your scripts or set the PERL5LIB environment variable.
Modifying @INC is quite easy. The best approach is to use the lib module (pragma) by adding the following snippet at the top of any of your scripts that require the locally installed modules:
use lib qw(/home/stas/lib/perl5/5.6.1/ /home/stas/lib/perl5/site_perl/5.6.1 /home/stas/lib/perl5/site_perl );
Another way is to write code to modify @INC explicitly:
BEGIN { unshift @INC, qw(/home/stas/lib/perl5/5.6.1/i386-linux /home/stas/lib/perl5/5.6.1 /home/stas/lib/perl5/site_perl/5.6.1/i386-linux /home/stas/lib/perl5/site_perl/5.6.1 /home/stas/lib/perl5/site_perl ); }
Note that with the lib module, we don't have to list the corresponding architecture-specific directories—it adds them automatically if they exist (to be exact, when $dir/$archname/auto exists). It also takes care of removing any duplicated entries.
Also, notice that both approaches prepend the directories to be searched to @INC. This allows you to install a more recent module into your local repository, which Perl will then use instead of the older one installed in the main system repository.
Both approaches modify the value of @INC at compilation time. The lib module uses the BEGIN block internally.
Now, let's assume the following scenario. We have installed the LWP package in our local repository. Now we want to install another module (e.g., mod_perl), and it has LWP listed in its prerequisites list. We know that we have LWP installed, but when we run perl Makefile.PL for the module we're about to install, we're told that we don't have LWP installed.
There is no way for Perl to know that we have some locally installed modules. All it does is search the directories listed in @INC, and because @INC contains only the default four directories (plus the . directory), it cannot find the locally installed LWP package. We cannot solve this problem by adding code to modify @INC, but changing the PERL5LIB environment variable will do the trick.
How to define an environment variable varies according to which shell you use. Bourne-style shell users can split a long line using the backslash (\):
panic% export PERL5LIB=/home/stas/lib/perl5/5.6.1:\ /home/stas/lib/perl5/site_perl/5.6.1:\ /home/stas/lib/perl5/site_perl
In the C-style shells, however, you'll have to make sure that the value of the PERL5LIB environment variable is specified as one continuous line with no newlines or spaces:
panic% setenv PERL5LIB /home/stas/lib/perl5/5.6.1: /home/stas/lib/perl5/site_perl/5.6.1: /home/stas/lib/perl5/site_perl
(In this example, the lines were split to make them fit on the page.)
As with use lib, Perl automatically prepends the architecture-specific directories to @INC if those exist.
When you have done this, verify the value of the newly configured @INC by executing perl -V as before. You should see the modified value of @INC:
panic% perl -V Characteristics of this binary (from libperl): Built under linux Compiled at Apr 6 1999 23:34:07 %ENV: PERL5LIB="/home/stas/lib/perl5/5.6.1: /home/stas/lib/perl5/site_perl/5.6.1: /home/stas/lib/perl5/site_perl" @INC: /home/stas/lib/perl5/5.6.1/i386-linux /home/stas/lib/perl5/5.6.1 /home/stas/lib/perl5/site_perl/5.6.1/i386-linux /home/stas/lib/perl5/site_perl/5.6.1 /home/stas/lib/perl5/site_perl /usr/lib/perl5/5.6.1/i386-linux /usr/lib/perl5/5.6.1 /usr/lib/perl5/site_perl/5.6.1/i386-linux /usr/lib/perl5/site_perl/5.6.1 /usr/lib/perl5/site_perl .
When everything works as you want it to, add these commands to your .tcshrc, .bashrc, C:\autoexec.bat or another equivalent file.[21] The next time you start a shell, the environment will be ready for you to work with the new Perl directories.
[21]These files are run by the shell at startup and allow you to set environment variables that might be useful every time you use your shell.
Note that if you have a PERL5LIBsetting, you don't need to alter the @INC value in your scripts. But if someone else (who doesn't have this setting in the shell) tries to execute your scripts, Perl will fail to find your locally installed modules. This includes cron scripts, which might use a different shell environment (in which case the PERL5LIBsetting won't be available).
The best approach is to have both the PERL5LIB environment variable and the explicit @INC extension code at the beginning of the scripts, as described above.
As we saw previously in this chapter, using the CPAN.pmshell to install mod_perl saves a great deal of time. It does the job for us, even detecting the missing modules listed in prerequisites, fetching them, and installing them. So you might wonder whether you can use CPAN.pm to maintain your local repository as well.
When you start the CPAN interactive shell, it searches first for the user's private configuration file and then for the system-wide one. For example, for a user stas and Perl Version 5.6.1, it will search for the following configuration files:
/home/stas/.cpan/CPAN/MyConfig.pm /usr/lib/perl5/5.6.1/CPAN/Config.pm
If there is no CPAN shell configured on your system, when you start the shell for the first time it will ask you a dozen configuration questions and then create the Config.pm file for you.
If the CPAN shell is already configured system-wide, you should already have a /usr/lib/perl5/5.6.1/CPAN/Config.pm file. (As always, if you have a different Perl version, the path will include a different version number.) Create the directory for the local configuration file as well:
panic% mkdir -p /home/stas/.cpan/CPAN
(On many systems, mkdir -p creates the whole path at once.)
Now copy the system-wide configuration file to your local one:
panic% cp /usr/lib/perl5/5.6.1/CPAN/Config.pm /home/stas/.cpan/CPAN/MyConfig.pm
The only thing left is to change the base directory of .cpan in your local file to the one under your home directory. On our machine, we replace /root/.cpan (which is where our system's .cpan directory resides) with /home/stas. Of course, we use Perl to edit the file:
panic% perl -pi -e 's|/root|/home/stas|' \ /home/stas/.cpan/CPAN/MyConfig.pm
Now that you have the local configuration file ready, you have to tell it what special parameters you need to pass when executing perl Makefile.PL. Open the file in your favorite editor and replace the following line:
'makepl_arg' => q[ ],
with:
'makepl_arg' => q[PREFIX=/home/stas],
Now you've finished the configuration. Assuming that you are logged in with the same username used for the local installation (stas in our example), start it like this:
panic% perl -MCPAN -e shell
From now on, any module you try to install will be installed locally. If you need to install some system modules, just become the superuser and install them in the same way. When you are logged in as the superuser, the system-wide configuration file will be used instead of your local one.
If you have used more than just the PREFIX variable, modify MyConfig.pm to use the other variables. For example, if you have used these variables during the creation of the Makefile:
panic% perl Makefile.PL PREFIX=/home/stas \ INSTALLPRIVLIB=/home/stas/lib/perl5 \ INSTALLSCRIPT=/home/stas/bin \ INSTALLSITELIB=/home/stas/lib/perl5/site_perl \ INSTALLBIN=/home/stas/bin \ INSTALLMAN1DIR=/home/stas/lib/perl5/man \ INSTALLMAN3DIR=/home/stas/lib/perl5/man3
replace PREFIX=/home/stas in the line:
'makepl_arg' => q[PREFIX=/home/stas],
with all the variables from above, so that the line becomes:
'makepl_arg' => q[PREFIX=/home/stas \ INSTALLPRIVLIB=/home/stas/lib/perl5 \ INSTALLSCRIPT=/home/stas/bin \ INSTALLSITELIB=/home/stas/lib/perl5/site_perl \ INSTALLBIN=/home/stas/bin \ INSTALLMAN1DIR=/home/stas/lib/perl5/man \ INSTALLMAN3DIR=/home/stas/lib/perl5/man3 ],
If you arrange all the above parameters in one line, you can remove the backslashes (\).
Just as with Perl modules, if you don't have the permissions required to install Apache into the system area, you have to install them locally under your home directory. It's almost the same as a plain installation, but you have to run the server listening to a port number greater than 1024 (only root processes can listen to lower-numbered ports).
Another important issue you have to resolve is how to add startup and shutdown scripts to the directories used by the rest of the system services. Without root access, you won't be able to do this yourself; you'll have to ask your system administrator to assist you.
To install Apache locally, all you have to do is to tell ./configure in the Apache source directory what target directories to use. If you are following the convention that we use, which makes your home directory look like the / (base) directory, the invocation parameters will be:
panic% ./configure --prefix=/home/stas
Apache will use the prefix for the rest of its target directories, instead of the default /usr/local/apache. If you want to see what they are, add the —show-layout option before you proceed:
panic% ./configure --prefix=/home/stas --show-layout
You might want to put all the Apache files under /home/stas/apache, following Apache's convention:
panic% ./configure --prefix=/home/stas/apache
If you want to modify some or all of the names of the automatically created directories, use the —sbindir, —sysconfdir, and —logfiledir options:
panic% ./configure --prefix=/home/stas/apache \ --sbindir=/home/stas/apache/sbin \ --sysconfdir=/home/stas/apache/conf \ --logfiledir=/home/stas/apache/logs
Refer to the output of ./configure —help for all available options.
Also remember that you can start the script only under a user and group to which you belong, so you must set the User and Group directives in httpd.conf to appropriate values.
Furthermore, as we said before, the Port directive in httpd.conf must be adjusted to use an unused port above 1024, such as 8080. This means that when users need to access the locally installed server, their URLs need to specify the port number (e.g., http://www.example.com:8080/). Otherwise, browsers will access the server running on port 80, which isn't the one you installed locally.
Now that we know how to install local Apache and Perl modules separately, let's see how to install mod_perl-enabled Apache in our home directory. It's almost as simple as doing each one separately, but there is one wrinkle. We'll talk about it at the end of this section.
Let's say you have unpacked the Apache and mod_perl sources under /home/stas/src and they look like this:
panic% ls /home/stas/src /home/stas/src/apache_1.3.xx /home/stas/src/mod_perl-1.xx
where x.xx are replaced by the real version numbers, as usual. You want the Perl modules from the mod_perl package to be installed under /home/stas/lib/perl5 and the Apache files to go under /home/stas/apache. The following commands will do that for you:
panic% perl Makefile.PL \ PREFIX=/home/stas \ APACHE_PREFIX=/home/stas/apache \ APACHE_SRC=../apache_1.3.xx/src \ DO_HTTPD=1 \ USE_APACI=1 \ EVERYTHING=1 panic% make && make test && make install panic% cd ../apache_1.3.xx panic% make install
If you need some parameters to be passed to the ./configure script, as we saw in the previous section, use APACI_ARGS. For example:
APACI_ARGS='--sbindir=/home/stas/apache/sbin \ --sysconfdir=/home/stas/apache/conf \ --logfiledir=/home/stas/apache/logs'
Note that the above multiline splitting will work only with Bourne-style shells. C-style shell users will have to list all the parameters on a single line.
Basically, the installation is complete. The only remaining problem is the @INC variable. This won't be correctly set if you rely on the PERL5LIB environment variable unless you set it explicitly in a startup file that is required before loading any other module that resides in your local repository. A much nicer approach is to use the lib pragma, as we saw before, but in a slightly different way—we use it in the startup file and it affects all the code that will be executed under mod_perl handlers. For example:
PerlRequire /home/stas/apache/perl/startup.pl
where startup.pl starts with:
use lib qw(/home/stas/lib/perl5/5.6.1/ /home/stas/lib/perl5/site_perl/5.6.1 /home/stas/lib/perl5/site_perl );
Note that you can still use the hardcoded @INC modifications in the scripts themselves, but be aware that scripts modify @INC in BEGIN blocks and mod_perl executes the BEGIN blocks only when it performs script compilation. As a result, @INC will be reset to its original value after the scripts are compiled, and the hardcoded settings will be forgotten.
The only time you can alter the "original" value is during the server configuration stage, either in the startup file or by putting the following line in httpd.conf:
PerlSetEnv Perl5LIB \ /home/stas/lib/perl5/5.6.1/:/home/stas/lib/perl5/site_perl/5.6.1
But the latter setting will be ignored if you use the PerlTaintchecksetting, and we hope you do use it. See the perlrun manpage for more information.
The rest of the mod_perl configuration can be done just as if you were installing mod_perl as root.
Resource Usage
Another important thing to keep in mind is the consumption of system resources. mod_perl is memory-hungry. If you run a lot of mod_perl processes on a public, multiuser machine, most likely the system administrator of this machine will ask you to use fewer resources and may even shut down your mod_perl server and ask you to find another home for it. You have a few options:
Reduce resource usage as explained in Chapter 21.
Ask your ISP's system administrator whether she can set up a dedicated machine for you, so that you will be able to install as much memory as you need. If you get a dedicated machine, chances are that you will want to have root access, so you may be able to manage the administration yourself. You should also make sure the system administrator is responsible for a reliable electricity supply and a reliable network link. The system administrator should also make sure that the important security patches get applied and the machine is configured to be secure (not to mention having the machine physically protected, so no one will turn off the power or break it).
The best solution might be to look for another ISP with lots of resources or one that supports mod_perl. You can find a list of these ISPs at http://perl.apache.org/.
Again, CPAN makes installation and upgrades simpler. You have seen how to install a mod_perl-enabled server using CPAN.pm's interactive shell. You have seen how to install Perl modules and Apache locally. Now all you have to do is to merge these techniques.
Assuming that you have configured CPAN.pm to install Perl modules locally, the installation is very simple. Start the CPAN shell, set the arguments to be passed to perl Makefile.PL (modify the example setting to suit your needs), and tell CPAN.pm to do the rest for you:
panic% perl -MCPAN -eshell cpan> o conf makepl_arg 'DO_HTTPD=1 USE_APACI=1 EVERYTHING=1 \ PREFIX=/home/stas APACHE_PREFIX=/home/stas/apache' cpan> install mod_perl
When you use CPAN.pm for local installation, you need to make sure that the value of makepl_arg is restored to its original value after the mod_perl installation is complete, because if you install other Perl modules you probably don't want to pass mod_perl flags to them. The simplest way to do this is to quit the interactive shell and then re-enter it. There is another way to do it without quitting, but it's very cumbersome—if you want to learn about the other option, refer to the CPAN.pm manpage.
Copyright © 2003 O'Reilly & Associates. All rights reserved.