Juan A. Navarro
Juan A. Navarro

Reputation: 11045

How can I use CPAN as a non-root user?

I want to install perl modules on a shared server on which I do not have root access. How can I do this? They also seem to have an older version of CPAN (it complains about that when running the command), is it possible to update the CPAN command being used from my account without requiring root access?

Upvotes: 86

Views: 47745

Answers (5)

Chas. Owens
Chas. Owens

Reputation: 64939

You can use cpanminus and the local::lib module.

The easiest method I have found so far is to say:

wget -O- http://cpanmin.us | perl - -l ~/perl5 App::cpanminus local::lib
eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`
echo 'eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`' >> ~/.profile
echo 'export MANPATH=$HOME/perl5/man:$MANPATH' >> ~/.profile

This assumes your profile is named .profile, you may need to change that to be .bash_profile, .bashrc, etc. After that you can install modules by saying

cpanm Module::Name

and simply use them the same way you would if the were installed in the root directories.


What follows is a brief explanation of what the commands above do.

Now,

  • wget -O- http://cpanmin.us fetches the latest version of cpanm, the cpa and prints it to STDOUT

  • The downloaded script is then piped to perl - -l ~/perl5 App::cpanminus local::lib: The first - tells perl to expect the program to come in on STDIN, this makes perl run the version of cpanm we just downloaded; perl passes the rest of the arguments to cpanm. The -l ~/perl5 argument tells cpanm where to install Perl modules, and the other two arguments are two modules to install:

    • [App::cpanminus]3 is the package that installs cpanm. This installation is how cpanminus bootstraps: The script we downloaded now installs itself as an app.
    • local::lib is a helper module that manages the environment variables needed to run modules in local directory.
  • Now that the installation itself is complete, we run:

    eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`
    

    to set the environment variables needed to use the local modules in this shell session, and

    echo 'eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`' >> ~/.profile
    

    to ensure we set them in our next login shell session.

  • Finally, we ensure future login shell sessions will have the local modules' man-help pages available for the man utility to search, with

    echo 'export MANPATH=$HOME/perl5/man:$MANPATH' >> ~/.profile
    

    this will hopefully cause man to find the man pages for your local modules.

Upvotes: 144

Yordan Georgiev
Yordan Georgiev

Reputation: 5440

we have been using the following func during the last 6 months on over 20 deployments successful automated deployments to aws ... called from the main provisioning as follows, which is basically just a copy paste of the answers above, but in a single re-usable bash script:

 #! /usr/bin/env bash                                                                                                                                                     │··  
                                                                                                                                                                           │··
  # a bash wrapper for check-installing required perl modules as non-root  
main(){                                                                                                                                                                  │··
     doSetVars                                                                                                                                                             │··
     doCheckInstallPreReqs                                                                                                                                                 │··
     perl $PRODUCT_INSTANCE_DIR/src/perl/my-perl-script.t                                                                                                                          │··
  }                                                                                                                                                                        │··
                                                                                                                                                                           │··
  doSetVars(){                                                                                                                                                             │··
     #set -x                                                                                                                                                               │··
     umask 022    ;                                                                                                                                                        │··
     set -u -o pipefail                                                                                                                                                    │··
     run_unit_bash_dir=$(perl -e 'use File::Basename; use Cwd "abs_path"; print dirname(abs_path(@ARGV[0]));' -- "$0")                                                     │··
     export PRODUCT_INSTANCE_DIR=$run_unit_bash_dir/../..                                                                                                                  │··
  }                                                                                                                                                                        │··
                                                                                                                                                                           │··
  doCheckInstallPreReqs(){                                                                                                                                                 │··
     eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`                                                                                                                         │··
     perl -e '                                                                                                                                                             │··
        use JSON ;                                                                                                                                                         │··
        use Data::Printer;                                                                                                                                                 │··
        use Test::Most ;                                                                                                                                                   │··
        use Test::Mojo;                                                                                                                                                    │··
        use Data::Printer ;                                                                                                                                                │··
        use FindBin;                                                                                                                                                       │··
        use JSON::Parse ;                                                                                                                                                  │··
        use IPC::System::Simple ;                                                                                                                                          │··
        use Mojolicious ;                                                                                                                                                  │··
     ' || {                                                                                                                                                                │··
           curl -L http://cpanmin.us | perl - -l ~/perl5 App::cpanminus local::lib                                                                                         │··
           eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`                                                                                                                   │··
           echo 'eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`' >> ~/.bashrc                                                                                               │··
           cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)                                                                         │··
           export PERL_MM_USE_DEFAULT=1                                                                                                                                    │··
           cpanm JSON Data::Printer Test::Most Test::Mojo Data::Printer FindBin JSON::Parse \                                                                              │··
              IPC::System::Simple                                                                                                                                          │··
           sudo curl -L cpanmin.us | perl - Mojolicious                                                                                                                    │··
     }                                                                                                                                                                     │··
                                                                                                                                                                           │··
  }                                                                                                                                                                        │··
                                                                                                                                                                           │··
  main

Upvotes: 0

Britton Kerin
Britton Kerin

Reputation: 477

If you want to be able to read man pages for the cpanminus-installed modules as well, you should also make sure the correct subdirectory of the chosen library path is in MANPATH. So the above solution showing the installation process of cpanm needs the following additional command:

 export MANPATH=$HOME/Library/perl5/man:$MANPATH' >> ~/.bash_profile

Upvotes: 2

DVK
DVK

Reputation: 129489

http://web.archive.org/web/20120427144232/http://perl.jonallen.info/writing/articles/install-perl-modules-without-root

http://novosial.org/perl/life-with-cpan/non-root/

The main step in both sets of instructions involves local::lib module

AFAIK, CPAN logic is contained in Perl module (CPAN.pm) which means you can also easily install the newer one in your local directory as you would with any other Perl module.


Also, once you install your modules in non-standard location, check out these two questions on loading libraries from non-standard locations (some of the info is already available in the link above):

How does a Perl program know where to find the file containing Perl module it uses?

How is Perl’s @INC constructed? (aka What are all the ways of affecting where Perl modules are searched for?)

Upvotes: 12

Juan A. Navarro
Juan A. Navarro

Reputation: 11045

For completeness, this is the installation process of cpanm on OSX if you want to keep your perl5 under ~/Library.

curl -L http://cpanmin.us | perl - -l ~/Library/perl5 App::cpanminus local::lib
eval `perl -I ~/Library/perl5/lib/perl5 -Mlocal::lib=~/Library/perl5`
echo 'eval `perl -I ~/Library/perl5/lib/perl5 -Mlocal::lib=~/Library/perl5`' >> ~/.bash_profile

Upvotes: 7

Related Questions