Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

#!/usr/bin/perl vs. -*- perl -*-

by why_bird (Pilgrim)
on Jan 20, 2009 at 11:32 UTC ( [id://737548]=perlquestion: print w/replies, xml ) Need Help??

why_bird has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,

Just wondering what the deal is with invoking a shell script with

#!/bin/sh #-*- perl -*- exec perl -x $0 "$@"
Rather than the "usual" (or should that be "beginner"?) method:
#!/usr/bin/perl
In perlrun it says something about being sure that Perl can read your switches---is this the only reason?

I originally thought it had something to do with portability between systems, but now think that may not be true because some systems don't recognise the shebang line at all.. or does that not matter when you invoke it the first way?

Then I thought that it might be for people who keep their perl in weird places or who want to be able to switch between versions of perl easily. Is that right? It seems most plausible!

I've tried searching with Google, but it just ignores all special characters, so no luck there. (This annoys me a lot actually, that they don't have some facility for specfically including special characters in the search.. on a complete tangent does anyone know a search engine that does?? or is there a way to make Google behave as I want?)

Cheers
why_bird
........
Those are my principles. If you don't like them I have others.
-- Groucho Marx
.......

Replies are listed 'Best First'.
Re: #!/usr/bin/perl vs. -*- perl -*-
by Tux (Canon) on Jan 20, 2009 at 11:42 UTC

    with #!/your/path/to/perl you force the use of a specific version of perl to be executed.

    The line #-*- perl -*- is for someone using emacs, and can be dropped. It should force emacs to use perl syntax highlighting, even if the command itself is a shell.

    The exec perl -x $0 "$@" line in the sh script executes the first perl executable found in $PATH, and would be somewhat equivalent to a header like #!env perl, which won't run on some systems. In both cases you have the risk of using modules that are not installed in either. Personally I always use the #!/my/personal/perl version.


    Enjoy, Have FUN! H.Merijn
      Further to the excellent response from Tux, I tend to use the form #!/usr/bin/env perl which pulls the version of perl from your environment - this is handier if, as I have, you one, or other, or both, of the following situations...
      • Different versions of perl against which you are(required to be) testing/running your code &/or...
      • Different *NIX platform configurations on which you are testing/running your code

      The above is, of course, moot if you have to run on Windoze, where all sorts of other problems come into play e.g. as you suggest, the shebang line is ignored etc. hence work-rounds have to be used e.g. batch files containing the full perl script (incl. the shebang line) together with the -x CLI option (see perlrun).

      A user level that continues to overstate my experience :-))

      Thankyou, that is a very clear explanation!

      Personally I always use the #!/my/personal/perl version.

      That makes me feel much better about using it and not like I'm missing some kind of obscure 'best practice' :)

      Cheers
      why_bird
      ........
      Those are my principles. If you don't like them I have others.
      -- Groucho Marx
      .......
Re: #!/usr/bin/perl vs. -*- perl -*-
by gone2015 (Deacon) on Jan 20, 2009 at 18:01 UTC

    My reading of perlrun suggests that Perl's behaviour is subtle:

    The #! line is always examined for switches as the line is being parsed. Thus, if you're on a machine that allows only one argument with the #! line, or worse, doesn't even recognize the #! line, you still can get consistent switch behavior regardless of how Perl was invoked...
    appears to say that:

    • if you happen to be running on a system that implements the #! trick, and invoke your Perl program in a way that causes the system to use the #!, then that's fine -- you'll get as many switches and such as the system is prepared to give you.

    • however, in any event Perl will parse the #! line itself and honour switches and stuff. So, if the system doesn't do it, or you run your program by (for example) perl my_wonderful_program.pl ...., you still get the switches from the #!.

      The documentation goes on to discuss what happens if switches appear both in the command line and in the #!, and to tell you that perl needs to appear somewhere on the line for Perl to be interested in it.

    So, Perl does more or less what you want. It has partly adopted the #! convention, so that even if it has no bearing on where the perl interpreter is run from, it still affects switches -- in a system independent manner.

    Update: except for -T as brother Hue-Bond points out below :-(

      • however, in any event Perl will parse the #! line itself and honour switches and stuff. So, if the system doesn't do it, or you run your program by (for example) perl my_wonderful_program.pl ...., you still get the switches from the #!.

      Yes but the -T switch wants to be in the command line too. perldiag explains that this is because when perl sees the -T switch, it's too late to taint some things.

      --
      David Serrano

Re: #!/usr/bin/perl vs. -*- perl -*-
by Argel (Prior) on Jan 20, 2009 at 18:53 UTC
    Barring some special circumstances you should really be hardcoding the perl you are using. And even if there are cross-platform compatibility issues that still doesn't justify leaving it up to your PATH because you can detect the system you are on and then run a hardcoded perl from within your wrapper shell script. Or alternatively you can modify the environment from within the shell script to make sure the perl you want will be first in your path (don't forget to check for aliases too). Rolling the dice is for role-playing games, not work! :-)

    Elda Taluta; Sarks Sark; Ark Arks

      Barring some special circumstances you should really be hardcoding the perl you are using.

      Why, might I ask? I've scratched my head over this for several minutes and I simply can't think of a good reason for doing this, except in the unusual case where you have multiple incompatible Perl interpreters installed at the same time.

      I certainly don't see how it could be a security thing. If someone's capable of adding a malicious perl binary to the $PATH of someone with superuser privileges, then the machine is probably rooted already.

      And even if there are cross-platform compatibility issues that still doesn't justify leaving it up to your PATH because you can detect the system you are on and then run a hardcoded perl from within your wrapper shell script.

      I'm not sure why you assume there's a wrapper shell script. I've never had any desire to use such a thing. #! /usr/bin/env perl works just fine.

      Where you have a heterogeneous set of environments, the last thing you want is a fragile script that lists half a dozen or more different magic filenames, and breaks if you upgrade a system. One of the nice things about Perl is that it lets you get away from shell scripts, which are a nightmare to make portable!

      And that's without even getting into the situation I'm commonly in, where I don't know what systems my scripts are going to run on. Sure, I could write a fragile shell script, and then when someone wants to run the script on Cygwin I could add another special case, and then when someone wants to run it on Solaris I could add yet another special case... or, you know, I could just put #! /usr/bin/env perl and it would just work on all the most common platforms, letting me reserve special-case handling for actual special cases.

        Why? It's good system administration, that's why. As I said in my original post, "rolling the dice is for role-playing games, not work!" In other words, you do not leave things to chance for things running in production. If you cannot grasp that concept then you just do not have enough system administration experience. You may want to read some "best practices" type books, such as "The Practice of System and Network Administration 2nd Ed" (publisher and Amazon links). Or work in a shop with several other developers and multiple Perl installations for some hands on experience.

        Your argument against a "fragile" wrapper script makes little sense because the entire system is "fragile". For example, you are concerned that an upgrade may break your wrapper script when an upgrade to the system will more likely break your Perl script.

        Your argument against a big complicated wrapper script also does not hold water. If the environments your code may run in are that different then you are going to have to do something about it anyway. If not then it is not going to be a complicated script. You are also moving into the realm of distributing code where a build environment would be more appropriate. What do you think happens when you do a "perl Makefile.PL"? Or a "./configure"?? Someone else has spent time figuring out how to resolve environment related issues for you. Quite frankly, it sounds like you are used to using packages created by others and thus have not been exposed to the work that went into making them. Have you ever tried compiling Perl or GCC?

        But at the heart of it all is that principle that you make sure you know what your production code is doing and what it is relying on.

        Elda Taluta; Sarks Sark; Ark Arks

Re: #!/usr/bin/perl vs. -*- perl -*-
by QM (Parson) on Jan 20, 2009 at 22:16 UTC
    For casual scripts, I've always used the following:
    eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' && eval 'exec perl -w -S $0 $argv:q' if 0; # The above invocation finds perl in the path, wherever it may be
    (I've forgotten where I stole this from.)

    Is there a "best" way to get whichever perl is in your path?

    I hadn't seen the env version before, nice.

    I also agree, in many cases the shebang line should point to a fixed Perl. I can even see an argument for not giving any shebang hints, and always invoking the perl binary explicitly from an external source.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://737548]
Approved by Corion
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (5)
As of 2024-03-29 12:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found