Shebangs with perlbrew aliases and EUMM (and without local::lib)

I wanted to comment on kevin spencer's perlbrew intro but my blabbering grew so long I chose to make a separate post instead.

shebangs

I used to use the #!/usr/bin/env perl trick for shebangs until (when reading about packaging executables with dists) I learned that ExtUtils::MakeMaker (and Module::Build) will automatically rewrite a full-path shebang to point to the interpreter used during install, but it specifically does not do this with the env trick.

I inadvertently combined 'env perl' with local::lib once and found that the script (reachable from my local::lib bin/) would die because I was trying to run a script in my path with a perl that didn't have that module installed (I must have switched perls in the meantime).

If the perl that installed the module is embedded in the script then calling it from the command line makes sure that it will be run by a perl that has the module installed (and has the same version that corresponds to the script using it). So it seems better to me to use the full path and let EUMM rewrite it.

tl;dr: use perlbrew alias to denote "current" version

I typically use one perl as my main perl and use a perlbrew alias to point to it:

perlbrew alias create perl-5.14.1 local

Then I can use

#!/home/rando/perl5/perlbrew/perls/local/bin/perl

for the shebang in all of my scripts.

Yeah, it's a little long, but I tab complete it or dump an env var rather than typing it out. This way any scripts that are part of dists I release will get rewritten by EUMM upon install and any scripts that are just for my personal use work with my "current" favorite perl.

When 5.14.2 is released I will install it, reinstall the modules I use, and change my perlbrew alias to point to it.

Sometimes I also symlink /usr/local/bin/perl to my perlbrew alias if I'm the only one on the machine or if perlbrew is in a location that is available to everyone (like /opt).

Then you can use the very common

#!/usr/local/bin/perl

which is shorter and easier to remember.

perlbrew and cpan modules

As a side note I do a perlbrew switch and use the cpan client to install modules directly into the perl lib dir (with the default installdirs site option) and I only use local::lib if I need to test a module with my system-provided perl.

That way (with modules installed relative to the perl that installed them) when you perlbrew switch if you haven't installed a module it's script won't even be found in your path.

If anyone has any points of contention or better suggestions, please share.

4 Comments

ln -s /home/rando/perl5/perlbrew/perls/local/bin/perl ~/.bin/perl

!~/.bin/perl

I still use /usr/bin/env perl

I just use your third tip, I always install my base set of modules on each perlbrew-installed perl.

Its a tradeoff, I just prefer to have my scripts run on the latest, current perl, without having to tweak my shebang lines.

Also, with the latest perlbrew's, you already have a stable path to the current perl, as ~/perl5/perlbrew/perls/current

So this is what I think would be the solution: If you author CPAN modules, any scripts in those modules should have a shebang that points to /usr/bin/perl.

If you're not writing stuff for CPAN but for your own use, choose /usr/bin/env perl instead.

And if you write for $Client, use his standards :D

Leave a comment

About Randy Stauner

user-pic perl -C -E 'say"i \x{2764} ",($^X =~ m#([^/]+)$#)'