Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Shebang behavior with perl

by McKreeger (Initiate)
on Mar 02, 2015 at 17:14 UTC ( #1118439=perlquestion: print w/replies, xml ) Need Help??
McKreeger has asked for the wisdom of the Perl Monks concerning the following question:

I have search documentation, but have not found an explicit answer as to why perl supports the following:

A simple shell script (foo.sh)
#!/bin/sh echo "Hello"
All of these work:
unix> foo.sh unix> sh foo.sh unix> perl foo.sh

The #! has to be the first line in the file, or it will not work. Is this a known/documented feature of perl?

Replies are listed 'Best First'.
Re: Shebang behavior with perl
by Corion (Pope) on Mar 02, 2015 at 17:17 UTC

    See perlrun at the end of the DESCRIPTION section.

Re: Shebang behavior with perl
by Anonymous Monk on Mar 02, 2015 at 17:18 UTC

    From perlrun:

    If the #! line does not contain the word "perl" nor the word "indir" the program named after the #! is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don't do #!, because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them.
Re: Shebang behavior with perl
by LanX (Bishop) on Mar 02, 2015 at 17:19 UTC
Re: Shebang behavior with perl
by McKreeger (Initiate) on Mar 02, 2015 at 17:39 UTC

    I've been exploring the use of:

    sample:
    #!/bin/sh echo "This is shell" SPECIAL_VAR=1 export SPECIAL_VAR eval "exec perl -x -S $(dirname $0)/$(basename $0) ${1+\"\$@\"}" #! -*- perl -*- -w use strict; print "This is Perl\n"; print "ARGV:".join(':',@ARGV)."\n"; print "SPECIAL_VAR: $ENV{SPECIAL_VAR}\n";

    as a means of initializing an environment prior to execution of given perl code. The above configuration will preserve quote strings so calls like:

    sample -multi "hello there" -single one

    Will keep the "hello there" as a single value in ARGV. The dirname/basename combo supports execution from ./ or any other path as dirname will return '.' if the script is called without a path

    The intent is to use "source .initenv" in the shell code to load environment initialization code shared across several perl scripts.

      I note that you are using perl -w to run your application. You probably likely will want to use warnings instead. -w will also cause other modules to emit warnings, even if they are not designed to run under the warnings pragma, which is probably not the behavior you usually want. use warnings; is lexically scoped, allowing you to control what modules you actually receive warnings from.

      --MidLifeXis

        Well, that situation was part of the motivation for the creation of "use warnings". But, I find that this motivation mostly no longer applies and that "use warnings" has its own problems and those are now worse than the problems of "-w" in most environments that I encounter.

        For example, it is fairly common to work in a manner where treating undef as either 0 or the empty string is not a problem. In such an environment, I don't enable warnings. But if I use a "modern" module, then it will have turned on warning for itself. When I pass one of these undefs into that module, I'll likely get a warning when the module tries to use that value as a string or as a number.

        So, in that case, "use warnings" causes the exact same problem as the one you claim I should avoid by using it.

        So I have better luck making sure that I always use "-w" in module tests and that I enable warnings in run-time environments where the warnings won't be useless (or worse). It has been a very long time since I ran into a problem with a module producing unwanted warnings due to my use of "-w". It has not been a long time since I've seen unwanted warnings from "use warnings" in a module.

        - tye        

Re: Shebang behavior with perl
by sundialsvc4 (Abbot) on Mar 03, 2015 at 04:49 UTC

    The explanation is quite simple:   “these are not Perl scripts!”   Therefore, the question of exactly what the Perl interpreter might do (or not ...) with a situation such as perl foo.sh becomes basically academic.

    Unix-shell programs are designed to read the first line of any “command file,” looking therein for a #!shebang™ line.   If they find one, they fork() the specified command, providing “the rest of the input-file” to the subprocess.   Then, the shell waits for the subprocess to complete.   And, that’s it.™

    “Shebang behavior,” therefore, has nothing to do with “Perl, or whatever-it-is.”

      Unix-shell programs are designed to read the first line of any “command file,” looking therein for a #!shebang™ line. If they find one, they fork() the specified command, providing “the rest of the input-file” to the subprocess.

      I doubt that. In modern unixes, the shell simply fork()s and then wait()s, and, in the child process, invokes exec(script,arguments). The kernel, not the shell, detects what kind of file is about to be executed, and runs the proper loader/interpreter. For dynamically linked ELF binaries, the proper loader name is embedded in the ELF file (something like /lib/ld-linux.so). For other file formats, a similar logic is used. For some file formats, a hard-coded or configurable helper program is invoked. For scripts that start with #!, the interpreter is the first "word" (block of non-whitespace characters) after #!. It may have an optional argument (everything up to end of line).

      Shells usually have some fallback code that handles a failing exec() for a text file, as required by POSIX.

      Links:

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      providing "the rest of the input-file" to the subprocess

      Misleading, as it implies the contents of the file, without the shebang line, are provided to the executed process; in fact, the file's name is provided as a command-line argument to the program specified on the shebang line.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2018-05-23 19:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?