/usr/local/bin rant

So, imagine you're a CentOS user, and you want to install a CPAN module into the system. Let's say you want to install cpanm.

You get the root shell with sudo -s.
You enter: cpan App-cpanminus.
And then you enter: cpanm --help... and oops:

[root@localhost vagrant]# cpanm --help
bash: cpanm: command not found

WAT?

What just happened is that cpan installs scripts into /usr/local/bin/, and /usr/local/bin/ is not in the root's $PATH.

I don't think CPAN toolchain is to blame here. But I think that if you can't run the software you just installed, something somewhere is horribly wrong.

But wait, there's more.
There're several different ways to get the root shell:

  1. sudo -s
  2. su -
  3. su

Let's see...

[vagrant@localhost ~]$ sudo -s
[root@localhost vagrant]# echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin

[vagrant@localhost ~]$ su
Password:
[root@localhost vagrant]# echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/vagrant/bin

[vagrant@localhost ~]$ su -
Password:
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

The first one, sudo -s, uses the secure_path option from /etc/sudoers.

The second one, su, inherits the current user's environment.

And the third one, su -, is the same as su -l, makes the shell a login shell, which resets the environment, so that it's the same as if you'd login with the root account initially.

But wait, it gets worse. Let's try cron:

[root@localhost ~]# crontab -l
* * * * * perl -E 'say $ENV{PATH}' >/tmp/cron.path

[root@localhost ~]# cat /tmp/cron.path
/usr/bin:/bin

Cron is the reason I wrote this post in the first place. The most popular complain about my Ubic these days is that it doesn't start services after the reboot. That's because Ubic bootstraps services on reboot with the crontab, which doesn't include /usr/local/bin/ (because there are many ways to setup Ubic, e.g., with perlbrew, so I didn't want to make any assumptions about the user's environment).
I'm giving up. I'm just going to always add /usr/local/bin to $PATH if it's not already there.

BTW, sudo -s $PATH issue is more RedHat-family specific, but cron's $PATH issue is not, as far as I know.

But why? What's the reason for all this? Is it for the sake of security? Can there really be such a program that's safe to keep in /usr/local/bin, accessible to all users, but not to the root? Really?

Authorization

PS: I know, I know, everyone should use Perlbrew. I agree, but don't forget to source $HOME/perl5/perlbrew/etc/bashrc everywhere, especially in your crontabs.

pp+1.pngIf you enjoyed this blog post, you could give me a +1 on the questhub for it.

13 Comments

cpan(1) installs to wherever your perl's config tells it to install, which is likely in the same place cpan(1) is. And, the -i switch there is just extra typing. :)

For cron, I don't rely on PATH at all:

PERL=....

* * * * * ${PERL} ...

Why are you using CPAN on CentOS? You should be installing these as RPMs. ;-)

cpan2rpm - There are many packages in the EPEL repo as well.

CPAN is an actual PITA for sys admins. When in Rome do as the Romans. Debian? use apt. RedHat use RPMs. Perl needs to become friendlier to system deployment and stop this CPAN madness. IMHO.

While I certainly understand your point, I completely disagree. Thanks to CPAN (and its clients) I can package once and distribute for every platform/distro, not having to package and repackage and repackage for every format. When the world settles on one installer format (that includes Mac/Windows), then I will happily stop using cpan clients.

/usr/local, on some platforms, is not secure. On other platforms, /usr/contrib is an unsecure location. There is a reason not to include it in root's default path.

Under cron (or system startup, or manually running scripted tasks), I typically have a launcher script that I use if I need to set up an environment. The reason is that I want to have an explicit environment when running things as root. As myself, that is an entirely different story, but as root, I want to know exactly what is going on.

--MLX

But the flipside is that knowing about the various package management tools is a PITA if you're a perl programmer who happens to have to admin various boxes :-)

I install Perl in a number of places, and like the fact that my chosen method for installing Perl and modules works the same on all of them.

That said, why don't you write a separate blog post on "packaging perl for sysadmins" or somesuch. I'd like to read opinions and suggestions from a more seasoned sysadmin on how to approach these sort of things.

Here's a nice thread that speaks to the cpan v package manager choice.

http://mail.pm.org/pipermail/melbourne-pm/2007-May/002316.html

I think developers prefer CPAN because they can immediately get things done, sys admins like order and integration of components into their environment that will play nice with their tool chains. Ultimately if you are deploying across multiple platforms flexibility is key, however in a homogenous environment rapid deployment using native tools is preferred. If the aim is a stable production environment (especially one that can be brought up and torn down quickly - think cloud) my vote is for package managers, even if I have to create my own repo and packages.

It's not a holy war for me however,in development mode I may delay creating a package and use CPAN temporarily, although this has the potential to become a rabbit hole quickly if some module is using Moose for example.

Again, not a holy war. Flexibility and pragmatism, and your particular use cases should dictate behavior instead of dogma and stubbornness.

Looks like your questhub/play-perl links are broken here.

Leave a comment

About Vyacheslav Matyukhin

user-pic I wrote Ubic. I worked at Yandex for many years, and now i'm building my own startup questhub.io (formerly PlayPerl). I'm also working on Flux, streaming data processing framework. CPAN ID: MMCLERIC.