Perl module version - perl

I have a couple of perl modules installed in the $HOME of my web server. The web server used to run perl 5.8.8 so they were installed under $HOME/perl/lib/perl5/5.8.8/...
During a server migration, the web hosting company changed perl to 5.10.1 but I did not know about this until my scripts started failing. I managed to do a quick dirty fix by copying the 5.8.8 tree to 5.10.1 and it seems to work OK now, but I want to avoid my scripts failing like this in future.
What is the best way of allowing my scripts to use the locally stored modules under the 5.8.8 folder even if the perl version gets upgraded again?
I can add a check for the expected perl version in my scripts and email myself if it changes, but it's too late by then as the script may have failed several times before I can fix the problem. Ideally I want to prevent the scripts failing at all.

Depending on the amount of flexibility you have when configuring your environment you may want to use Perlbrew.
to maintain an independent Perl installation at a specific version. This can avoid nasty surprises when the system-wide Perl installation changes.

The thing you really should do is ensure that your needed modules are installed in the new installation. Especially for XS (C-level) modules there is no guarantee that they will run on a new version of Perl without recompiling since the core may have changed.
You should make a Makefile.PL or Build.PL which declares the dependencies of your scripts and you company should make it a policy to execute those scripts on server migration.
Finally, yes you can check $^V which is the running Perl. And if you do it inside a BEGIN block it will be executed during startup. In fact you can use local directories for your (pure perl) modules and then point to them using the lib module.

Why did you move the files at all? Just keep add to PERL5LIB instead.
PERL5LIB=$HOME/perl/lib/perl5/5.10.1:$HOME/perl/lib/perl5/5.8.8
I strongly recommend that you simply use perlbrew to install a build of Perl in your home directory instead of being at your host's mercy.

Related

Bundling up a perl script with its dependencies?

I have a perl script that I've put together to do some monitoring and graphing.
It works nicely on my dev system, where I have carte-blanch to install my own modules from CPAN.
What I'm looking at doing is bundling it up to deploy onto another system. But here's the catch - this other system is 'standalone' and has no network connection. (And I have change control paperwork to fill in, indicating what I'm installing).
As a result, I'd really like a nice easy way to figure out:
- What modules my scripts are making use of. (Including dependencies)
- how to easily grab them (cpan get probably)
- Is there an easy way to tell what external binaries I'm using? (I'm using for sure ssh and rrdtool - the former is definitely installed, the latter probably not).
I have a few thoughts on how to do this, but it strikes me as something that should be smoother.
I may also need to deploy a new perl, so I'm pondering whether I'm better off 'installing' the modules with system perl (probably 5.8.8 on RHEL5), or just 'packaging' the whole thing in a directory of it's own with a standalone perl instance.
Use pp to package your script and all dependant modules and libraries into a stand alone executable.
pp -x yourscript.pl -o outputfilename
See the documentation for examples of how to link to external shared objects (etc) if required. With pp you don't need perl on the target system where outputfilename will run.
Revisiting this, as the need hasn't really gone away. I have moved towards using docker - this is an 'image' and 'container' system for app deployment, which amongst other things, allows you to 'package' an application.
You create a Dockerfile - which is analagous to a Makefile - that runs through the steps to install perl + dependencies (either via a package manager, or from CPAN).
Once it has, you have a self contained, runnable 'image' that you can clone and create an instance of (a "container" in docker parlance).
It's also quite useful - even if you don't then deploy via container - to figure out what the dependencies of this application/packages were. The version in the container has everything locally installed that it needed, because it was a clean build.
When you have a system where you can't control the Perl installation (and the install is a really, really old version of Perl like 5.8.8 which is missing many nice improvements like state variables, autodie, say, and switch), you should look into Perlbrew.
Perlbrew allows you to install a user version of Perl. (In fact, it allows you to install multiple versions of Perl), and allows you to switch between the Perlbrew install and the officially installed version. It makes doing everything in Perl much, much easier.
You will have freer access to install new Perl modules, and you can do that task yourself rather than wait for your IT department to do it for you.
I ended up using it on one of our systems where the primitive version of Perl just wasn't doing what my version of Perl did. I originally asked our IT to upgrade, but they really messed up the upgrade. After going back and forth, I simply asked if I could install Perlbrew.
Which is an important point. Always ask permission. A lot of time, the IT department is more than happy to oblige. They're not Perl people, and CPAN is a world they don't want to deal with. Being able to get out of having to answer your beck and call about installing this or that Perl module is a great relief.

Is it possible to install perl prerequisites before distribution testing and how?

I try to build a Perl distribution for a home-made module, from the Module::Starter base. Every test pass on my machine, but when I upload it to CPAN to get some more universal tests from cpantesters.org, some test failed on other architectures or OS, but I can't understand why. I can see in test reports that some of my prerequisites are not installed before testing but I would like it to.
I've tried to list these dependencies into the Makefile.PL PREREQ_PM hash and then in the TEST_REQUIRES hash, but it didn't changed a lot of results.
Then, when I've removed the dependencies from my local machine and tried to install my module using Cpanm, it downloads dependencies first, test passed and install has been a success.
This is my first try for a module, so I think I am missing something, maybe I am too used of the Cpanm magic. Thanks for any help.
The problem is something different. Andreas' smoker very probably built the dependency App::Ack (which looks in the fail reports like being absent) successfully. But here come at least two problems:
When a distribution gets tested, then its dependencies may or may not be installed already. However, it's guaranteed that all dependent modules are made available through the PERL5LIB environment variable, so make test usually works (To be more specific, if the install Module command is used in the CPAN shell, then all dependencies are installed immediately. If the test Module command is used, then dependencies are only built, but not installed. The CPAN user can do the installation later using install_tested). So it may be that App::Ack is not installed here, just built. Especially this means that the ack script is not installed in the final location.
Even if it is installed, many smoke testers or users who have multiple perls installed in parallel use a non-standard directory for this perl. So ack wouldn't be installed in /usr/bin or /usr/local/bin, but in the bin directory belonging to this perl. This directory may or may not be in the user's PATH at all. So you cannot assume that can_run("ack") works here. A workaround here is to add $Config{scriptdir} temporarily to $ENV{PATH}. Another solution would be to use the App module instead of the script, if it's possible. Unfortunately it looks like ack can only be called as a script.
If you look at a sample fail report, then you can see that App::Ack was installed (it appears in the PREREQUISITES section both under requires and build_requires, you can also see which App::Ack version is installed in the "HAVE" column). You can also see the user's PATH (in the ENVIRONMENT section). And you may guess about the scriptdir for this perl, it's usually the same directory where the perl binary itself is installed, and the path to current perl is visible in $^X (under "Perl special variables").
If you want to reproduce the behavior, then you need to deinstall ack from your machine, build a custom perl using ./configure.gnu --prefix=/path/to/custom/perl-5.X.Y, and use this perl for tests.

SOAP::Lite module installation on cPanel

I am creating a custom module to be placed in the directory /usr/local/cpanel/Cpanel. My perl module requires SOAP::Lite. Since the scripts placed in the directory /usr/local/cpanel/Cpanel are run under cpanel's internal perl version 5.6.2, does on install the SOAP::Lite module?
Trying to build the module with cpanel's build tool fails as another perl module is require to build the source module for soap::lite from cpan.
Perl modules are usually installed using the cpan program that comes with Perl. This checks all the dependencies for you and installs everything you need. This is what you should do.
If you don't have the ability to access and run this program, then you may not have permission to install modules at all. Possibly you could get whoever is running your system to do it for you (also ask them to upgrade your nearly 9 year old version of Perl while they are at it!).
Beyond that, there are not many options. You could try building the required modules on another, similar system and copying over--if you enjoy pain.

Is it safe to have various Perl installations on one machine share a cpan_home?

I have a dated system perl 5.8.8 on a Linux machine and installed a 5.12.4 from ActiveState. Both perl's cpan_home is ~root/.cpan. I was about to change the new perl's cpan_home, but then I realized I didn't know whether I really have to do this or whether it would just result in multiple copies of modules being downloaded to different directories when in fact they could be shared.
So can they? Is it safe? With regard to compiling? Or do I have to go for separate cpan_home directories?
Note that I tried perlbrew first but it failed with Can't load '../lib/auto/IO/IO.so' for module IO: ../lib/auto/IO/IO.so: wrong ELF class: ELFCLASS64 at ../lib/XSLoader.pm line 70. So instead of pursueing the issue I went for ActivePerl, which installs easily.
I have a dozen builds of Perl on my system, and they all use ~/.cpan. I have never had a problems, but I cannot say that it is safe. It depends on the settings therein. Specifically,
build_dir_reuse should (probably) be zero.
makepl_arg shouldn't contain INSTALL_BASE.
mbuildpl_arg shouldn't contain --install_base.
"Install base" overrides where the modules are installed. If you start installing the modules for all your builds in one location, you will have problems due to incompatibilities between versions, releases and builds of Perl.
If you want to share .cpan and have a local install directory, you can probably get away with using PREFIX=/home/username/perl5 LIB=/home/username/perl5/lib instead of INSTALL_BASE=/home/username/perl5. It uses a smarter directory structure.
By the way, local::lib causes "install base" to be used, so you'll run into problems if you use local::lib with multiple installs of Perl.

How do I use a vendor Apache with a self-compiled Perl and mod_perl?

I want to use Apple's or RedHat's built-in Apache but I want to use Perl 5.10 and mod_perl. What's the least intrusive way to accomplish this? I want the advantage of free security patching for the vendor's Apache, dav, php, etc., but I care a lot about which version of Perl I use and what's in my #INC path. I don't mind compiling my own mod_perl.
Build your version of Perl 5.10 following any special instructions from the mod_perl documentation. Tell Perl configurator to install in some non-standard place, like /usr/local/perl/5.10.0
Use the instructions to build a shared library (or dynamic, or .so) mod_perl against your distribution's Apache, but make sure you run the Makefile.PL using your version of perl:
/usr/local/perl/5.10.0/bin/perl Makefile.PL APXS=/usr/bin/apxs
Install and configure mod_perl like normal.
It may be helpful, after step one, to change your path so you don't accidentially get confused about which version of Perl you're using:
export PATH=/usr/local/perl/5.10.0/bin:$PATH
You'll want to look into mod_so
I've done this before. It wasn't pretty, but it worked, especially since vendor perl's are usually 2-3 years old.
I started with making my own perl RPM that installed perl into a different location, like /opt/. This was pretty straight forward. I mostly started with this because I didn't want the system utilities that used perl to break when I upgraded/installed new modules. I had to modify all my scripts to specify #!/opt/bin/perl at the top and sometimes I even played with the path to make sure my perl came first.
Next, I grabbed a mod_perl source RPM and modified it to use my /opt/bin/perl instead of /usr/bin/perl. I don't have access to the changes I made, since it was at a different gig. It took me a bit of playing around to get it.
It did work, but I'm not an RPM wizard, so dependency checking didn't work out so well. For example, I could uninstall my custom RPM and break everything. It wasn't a big deal for me, so I moved on.
I was also mixing RPM's with CPAN installs of modules (did I mention we built our own custom CPAN mirror with our own code?). This was a bit fragile too. Again, I didn't have the resources (ie, time) to figure out how to bend cpan2rpm to use my perl and not cause RPM conflicts.
If I had it all to do again, I would make a custom 5.10 perl RPM and just replace the system perl. Then I would use cpan2rpm to create the RPM packages I needed for my software and compile my own mod_perl RPM.