Jerry Jerry - 4 months ago 14
Perl Question

A change of shebang + eval leads to the perl script failure

This is a question derives from another post. Based upon the comments and answer from that post, I change the following shebang + eval into another one:

Old works version

#!/bin/perl
eval 'exec perl5 -S $0 ${1+"$@"}'
if 0;


New doesn't work version

#!/bin/sh
eval 'exec perl5 -S $0 ${1+"$@"}'
if 0;


Notice that I change
#!/bin/perl
to
#!/bin/sh
and based upon my understanding, the new version should also work because the script is treated like shell script and
eval
get executed and
perl5
is invoked to use perl to execute the same script. However, when I actually run this, I got:

/bin/sh: -S: invalid option


Can anyone explain why this case the script is failed. Do I misunderstand something? I'm using
ksh


Also this web page I found online seems suggest that my new version should work as well.

Thanks much!

Answer

From the Perl documentation:

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.

So if you launch the modified version as ./script:

  1. Your shell executes ./script
  2. The kernel actually executes /bin/sh ./script
  3. sh executes perl5 -S ./script
  4. perl5 executes /bin/sh -S ./script because it sees a shebang that doesn't contain perl.
  5. sh dies because it doesn't recognize the -S option.

And if you launch the modified version as perl5 script:

  1. Your shell executes perl5 script
  2. perl5 executes /bin/sh -S script because it sees a shebang that doesn't contain perl.
  3. sh dies because it doesn't recognize the -S option.

Also this web page I found online seems suggest that my new version should work as well.

The code on that page is significantly different than the code you used. In that code, there's an explicit instruction (-x) to ignore the actual shebang line, and to look for one that contains perl later in the file (which is also missing from your code).

Comments