10

Obviously this applies equally with python, bash, sh, etc substituted for perl!

Quentin's answer below was clearly correct, and so I've accepted it, but I guess what I actually meant was 'what are the pros and cons of the two ways of using #! to invoke perl/python/bash as the interpreter of a script?'

agf
  • 171,228
  • 44
  • 289
  • 238
John Lawrence Aspden
  • 17,124
  • 11
  • 67
  • 110
  • This question doesn't really have anything to do with specific scripting languages, but I left it tagged perl because that's the example used in the title. – agf Sep 30 '11 at 10:22

4 Answers4

13

One references a common place that perl is installed. The other references a common place that env is installed and asks it what the path to the default perl is.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
9

These are good rules, if you have a good reason to break them, don't hesitate to do so:

Use #!/usr/bin/env perl where possible for portability between heterogenous systems. But that's a dumb way to do it because it makes the assumption that the Perl that is first in the path is also the Perl you always want. That may not be so, and usually when there are several Perls on a system they are there for a certain reason.

A better approach is to package scripts up in a CPAN-ready distro. Distribute the distros to the systems where you want to have them installed and install them in the usual way (manually or with the CPAN toolchain), specifiying the full path to perl or cpan. During that process, the shebang line is rewritten to the correct path to Perl.

Examples:

tar -xvf Local-OurCompany-Scripts-1.000.tar.gz
cd Local-OurCompany-Scripts-1.000

## automated installation
/usr/bin/cpan .
# or perhaps
/opt/ourcompany/perls/perl-5.14.2/bin/cpan .

## manual installation
/usr/bin/perl Makefile.PL ; make ; make install
# or perhaps
`which perl5.14.2` Makefile.PL ; make ; make install
daxim
  • 39,270
  • 4
  • 65
  • 132
  • 2
    But you forget that manipulating the path is easily done - using `env` allows you to use different perls for different programs (or even the same program at different times). Using a hardcoded perl path and CPAN's path rewriting capability makes the assumption that the perl used to do the installation is the perl you always want, which I would argue is a bigger (and worse) assumption than that made by `env`, as it requires modifying the source to override it, rather than a simple "PATH=/path/to/other/perl:$PATH some_perl.pl". – Dave Sherohman Oct 01 '11 at 10:39
  • I agree with this part: _"But that's a dumb way to do it because it makes the assumption that the Perl that is first in the path is also the Perl you always want."_ and would add that it assumes your script will work fine with any given instance of Perl (and Perl-Modules) it finds. – Gonen Aug 13 '14 at 06:47
5

Using env to find the executable, rather than finding it yourself, does an additional exec, but that shouldn't really matter most of the time. It's convenient and I often use it myself.

However, I have had issues with people using env in system scripts. On one occasion, installing a /usr/local/bin/perl broke my system so that I could not update it anymore until I resolved the problem. On another occasion, installing a /usr/local/bin/python broke the ID3 tagger I was using. I think this is more a packaging issue than an inherent problem with env. If you're installing something on a system, why are you carefully checking that it has a version of Python that satisfies all of your dependencies if you're just going to leave a shebang line that fishes around for any old version of Python each time it is run?

oylenshpeegul
  • 3,404
  • 1
  • 18
  • 18
  • I see no reason why `env` should fork another process. Did you mean "execs", or alternately would you mind expanding on the subject? – JB. Sep 30 '11 at 12:36
1

I can give you a concrete example:

Imagine you have a LAMP package installed in /opt/ (i.e. XAMPP) that includes it's own perl executable, libraries and pakage manager.

You actually want to run that executable so you add the path to the LAMP executables in your PATH environment variable (PATH="/opt/XAMPP/bin:$PATH").

Now any script that uses "#!/usr/bin/env perl" will execute the perl binary in the LAMP stack directory. The other path will execute the pre-installed perl binary in your system, in "/usr/bin/perl".

It's up to you to decide what's better for your perl script.