Install Perl Modules without root

How many times Perl developers have to scratch their heads when they find that there is a module dependency which is breaking their code. Worse, they do not have sufficient privileges to install the required modules on the system. And the worst - there is no immediate way to get the module installed and the application needs to be tested/deployed ASAP! Well, I faced a similar situation during my experience in deploying a website on a shared hosting account, where I was on the mercy of the Hosting Service Provider to decide which modules I’m going to use and which not. But this is hardly the way a programmer works, and more so for a Perl programmer! I came across a few wonderful workarounds (hacks!) to overcome the above.

Download the module from CPAN or elsewhere. Place it in any directory, where you have permissions. Preferably, create a directory called

lib

in the application directory and place your module there. Untar it, you will see a few files and folders - Makefile.pl (to install the module, we don’t need this) , Readme.txt (this either), Examples (not required), lib directory - this is the only thing we are concerned with. It contains the main module files. Go inside the lib directory, and copy all the folders (if any) and all .pm files and place them directly inside the lib directory you just created. Remove all other files and folders.

The next thing which you need to do is go to the Perl code where you want to use that module and write the following:

BEGIN { unshift @INC, "./lib"; }
use Module::Name;

And voila!! Your code works like a charm with all the functionalities of the module included.

How it works? - When you use a module in a program, like

use CGI::Ajax;

perl searches for it in a predefined library search path on the system. You can determine which directories are in the path by executing

perl -e 'print for @INC;'

Any module in order to be usable in the program needs to be in any of the directories above, which is where the modules get installed if installed via

cpan or ppm

command or using Makefile.pl.

But in the situation discussed, it is not the case, as we cannot install a module as it should be. Instead what we do is place the modules in a directory of our choice (lib) and then insert the path of that directory in the

@INC

so that later when the perl interpreter tries to do

use Module::Name;

it finds its path in

@INC

Why BEGIN { } ? -

use Module::Name

happens at compile time, when the interpreter reads the program while

unshift @INC, "./lib"

happens at run-time, after the compilation, i.e, attempt to load the module, even if the latter is placed above the former in the program. So in order to force the program to modify

@INC

before trying to use the module, we use

BEGIN { }

block. Any code which is written within

BEGIN { }

block is executed at compile-time as opposed to other code which is executed at run-time.

Note: Remember that many modules have further dependencies, i.e. modules which are required for the former to work. And if these dependencies are not on the system, the code won’t work. You need to perform the above operations for each of those dependencies as well. For example, if CGI::Ajax requires Class::Accessor to work, you need to

a) create the directory CGI and place Ajax.pm within it

b) create the directory Class and place Accessor.pm and the directory Accessor within it and

c) unshift/push the path of the directory which contains these 2 directories CGI and Class, into @INC.

I have used this method to use more than 30 odd modules and have faced no difficulty whatsoever. However it will not work if the module’s Makefile.pl does more than just copying the .pm files in the right place and do some other work such as using external C libraries etc.

Another method of extending

@INC

is setting the

PERL5LIB

environment variable on your system to include the path of the manually placed modules.

In Bourne Shell do something like-

PERL5LIB=/path/to/module/directory; export PERL5LIB

It is useful when you do no want to write the BEGIN blocks in all the files where you use the module. But only users who are setting the

PERL5LIB

environment variable can only use it and other users can’t.

Spread the Word:
  • Digg
  • del.icio.us
  • StumbleUpon
  • Slashdot
  • Netvouz
  • description
  • blogmarks
  • Furl
  • IndiaGram
  • IndianPad
  • Reddit
  • Simpy
  • e-mail
  • Facebook
  • Google
  • Live
  • Technorati
  • YahooMyWeb
  • TwitThis

RSS feed | Trackback URI

5 Comments »

Comment by Dave Doyle CANADA Mac OS X Mozilla Firefox 2.0.0.6
2007-10-17 19:25:24

There is another way to do this:

use lib ‘./lib’;

Using the lib module takes away the need for a BEGIN block and is considered a better practice. You can add multiple directories to @INC by providing lib a list as well:

use lib qw(./lib ./project_lib);

You may want to consider fully qualified paths as well.

The PERL5LIB environment variable is handy as well to avoid the problem as well. People should know though that if you are running this on a server PERL5LIB won’t work if you are running Perl as CGI under suexec (common on shared web hosts). Although I haven’t tried it, if you have the ability to edit your .htaccess files (apache config overrides file) you could probably do a:

SetEnv PERL5LIB ./lib;./project_lib;

To set that up in the server’s environment which executes the script. Not sure if that’ll work though.

It’s also worth noting that if you have shell access on a shared webhost you can install your own CPAN modules above and beyond what the server has by creating your own Perl modules directory. Dreamhost has a nifty article on their wiki on how to do this. It works pretty well though you may wish to avoid messing with the DBI (often they’re older and newer versions may not compile). You can see their article on the matter at:

http://wiki.dreamhost.com/CPAN

I’m sure the directions can be pretty easily adapted to other hosts.

 
Comment by Naveen INDIA Windows XP Mozilla Firefox 2.0.0.7
2007-10-17 22:58:32

There is another way to do this:
use lib ‘./lib’;
Using the lib module takes away the need for a BEGIN block and is considered a better practice. You can add multiple directories to @INC by providing lib a list as well:
use lib qw(./lib ./project_lib);
You may want to consider fully qualified paths as well.
The PERL5LIB environment variable is handy as well to avoid the problem as well. People should know though that if you are running this on a server PERL5LIB won’t work if you are running Perl as CGI under suexec (common on shared web hosts). Although I haven’t tried it, if you have the ability to edit your .htaccess files (apache config overrides file) you could probably do a:
SetEnv PERL5LIB ./lib;./project_lib;
To set that up in the server’s environment which executes the script. Not sure if that’ll work though.
It’s also worth noting that if you have shell access on a shared webhost you can install your own CPAN modules above and beyond what the server has by creating your own Perl modules directory. Dreamhost has a nifty article on their wiki on how to do this. It works pretty well though you may wish to avoid messing with the DBI (often they’re older and newer versions may not compile). You can see their article on the matter at:
http://wiki.dreamhost.com/CPAN
I’m sure the directions can be pretty easily adapted to other hosts.

Hi Dave,
Thanks for the lovely insight and detailed explanations above. Yes I know about the use lib approach but was no quite sure which one is better. Thanks again for the same.

 
Comment by Naveen INDIA Windows XP Mozilla Firefox 2.0.0.11
2007-12-15 22:48:21

very interesting, but I don’t agree with you
Idetrorce

Don’t agree with what exactly? If you can explain Idetrorce.

 
Comment by Ned PHILIPPINES Windows XP Mozilla Firefox 2.0.0.6
2008-06-24 16:50:57

Does this work in crons?
I used your approach, however, my script doesn’t run in the cron - for manual run, it does work fine.

Thanks,
Ned

Comment by Naveen INDIA Windows XP Mozilla Firefox 3.0
2008-07-16 22:15:00

First, my sincere apologies for not being able to reply to your message for so long. In most likelihood, you have not given full absolute path of the perl library you’re trying to include, hence it’s having problems in cron. If you still have this problem open, you can post the exact statements which you use, and I can have a look at it.

 
 
Name (required)
E-mail (required - never shown publicly)
URI
Subscribe to comments via email
Your Comment (smaller size | larger size)
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> in your comment.

Trackback responses to this post

139897 pages viewed, 70 today
59394 visits, 34 today
FireStats icon Powered by FireStats