Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Re^2: shebang anomaly

by perlboy_emeritus (Sexton)
on Apr 18, 2018 at 22:48 UTC ( #1213143=note: print w/replies, xml ) Need Help??

in reply to Re: shebang anomaly
in thread shebang anomaly

Thanks choroba, but I don't think that article is on point for my problem. Let me state it again but more precisely. Every one of my Perl scripts has these two opening lines:
#!/usr/bin/env perl -w ##!/usr/bin/env perl -wd

I switch between these two lines, the first for ordinary runs, the second for debug runs. When I wish to debug I invert the lines, comment out the second, uncomment the first and proceed. Both these shebang lines fail in debian but work correctly in macOS. In debian I cannot have any argument to perl from an /usr/bin/env shebang despite rtfm. That page says the command can take an argument. True, if the argument was an argument list I would certainly quote it so that it appears as a single argument. In both of those example shebangs, I cannot have any arguments no matter how I quote them, and I've tried every quote option there is.

Replies are listed 'Best First'.
Re^3: shebang anomaly
by huck (Parson) on Apr 19, 2018 at 00:00 UTC

    The shebang line has never been specified as part of POSIX, SUS, LSB or any other specification. AFAIK, it hasn't even been properly documented.
    There is a rough consensus about what it does: take everything between the ! and the \n and exec it. The assumption is that everything between the ! and the \n is a full absolute path to the interpreter. There is no consensus about what happens if it contains whitespace.

    1 Some operating systems simply treat the entire thing as the path. After all, in most operating systems, whitespace or dashes are legal in a path.
    2 Some operating systems split at whitespace and treat the first part as the path to the interpreter and the rest as individual arguments.
    3 Some operating systems split at the first whitespace and treat the front part as the path to the interpeter and the rest as a single argument (which is what you are seeing).
    4 Some even don't support shebang lines at all.

    Thankfully, 1. and 4. seem to have died out, but 3. is pretty widespread, so you simply cannot rely on being able to pass more than one argument.

      Option 3 is much like MS DOS and its successors: make every program parse its own command line.

      Given that quoting in DOS is so difficult, most people don't try to write perl one-liners there. (Granted, it's hard enough in *shell sometimes.)

      Quantum Mechanics: The dreams stuff is made of

Re^3: shebang anomaly
by pryrt (Monsignor) on Apr 19, 2018 at 13:54 UTC

    I don't know if you ever gathered this from the other replies, but from choroba's "interpreter and parameter" and your "in both of those example shebangs, I cannot have any arguments" shows that, at least originally, you didn't understand. In the shebangs

    #!/usr/bin/env perl -w ##!/usr/bin/env perl -wd
    The "/usr/bin/env" is the interpreter, and "perl -w" or "perl -wd" is the single parameter (argument). Because it's one entity, then some versions of env will try to run "perl -w", and doesn't find anything to run that's P E R L SPACE DASH W as the name. (the same as you might get on other systems if you tried /usr/bin/env 'perl -w' or /usr/bin/env 'perl\ -w'.)

Re^3: shebang anomaly
by bliako (Prior) on Apr 19, 2018 at 09:46 UTC

    Apart from all the examples given, there is a script in that page called "cmd" which allegedly will solve your problem by using: #!cmd /usr/bin/env perl -w. However, unless I am doing something wrong, it does not work for me. Although it should because what it does is straight-forward: breaks the command line and spawns yet another perl process with these args and your actual perl script.

    Maybe you will have better luck than me if you were to try having two shell scripts and calling perl differently?

      I contacted the maintainers of GNU coreutils of which env is a component and the answer I got really pissed me off, so I am forced to write my own env for use in debian (env behaves as expected in macOS). Printing the environment is the least difficult of what env does. That can be done with six lines of C, as in:

      #include <stdio.h> int main(int argc, char** argv, char** envp) { while (*envp++) { printf("%s\n", envp[-1]); } }

      The more challenging part, or parts, is the other things that env does and to make it work the same whether it is called from the command line or as a shebang. I subscribe to the principle of "least surprise", as in this article:

      I'll start with the code in cmd, as reported by choroba in an earlier post and go from there. It is fairly obvious to me that a well-behaved env could be implemented in any of C, bash or Perl. I might try them all, just to explore the possibilities. The GNU coreutils team should learn some humility, since a utility program's purpose is to enable users to do what they want to do, not assert some arrogant notion of "not-invented-here." I maintain that GNU env is either stupid or broken because it does not behave in a shebang the way it does when called from a command line. These two methods of invocation should not produce different results, no matter how aggressively someone asserts the program behaves correctly.

        So you want an env that works in a DWIM manner? How should it detect whether it was invoked from command line or from shebang? Note that it is the OS that passes a single argument to env. To rectify this, you'd have to change the way OS behaves.

        FWIW, Linux supports custom executable formats (binfmt_misc). You could actually hack up a fancy that is shebang capable, and arrange this to handle your scripts as well. But then you'd have to decide how to parse/split the argument string: just split it at whitespace, or use shell escaping rules? Which shell? All in all, that's a horrible can of worms, which is probably why the shebang is as it is today.

        If you absolutely need a perl environment that is predictable and reliable, then the program path is the least of your worries. You'd most likely bundle your own perl and modules in that case, and know the path of your binaries.


        But beware the can of worms Anonymous Monk already warned you about, re: the breaking of the command line, shell escapes and nested quotes.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1213143]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2020-11-23 16:29 GMT
Find Nodes?
    Voting Booth?

    No recent polls found