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!
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
:
- Your shell executes
./script
- The kernel actually executes
/bin/sh ./script
sh
executes perl5 -S ./script
perl5
executes /bin/sh -S ./script
because it sees a shebang that doesn't contain perl
.
sh
dies because it doesn't recognize the -S
option.
And if you launch the modified version as perl5 script
:
- Your shell executes
perl5 script
perl5
executes /bin/sh -S script
because it sees a shebang that doesn't contain perl
.
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).