1

I've read somewhere that in Linux a shebang line (#!) can't exceed 127 characters. I have a Perl script which has a shebang line of over 300 characters, and it hasn't failed (yet). Does the limit apply only to the executable path (which is under 100 chars in my case), or is there some strange magic at work?

Mark VY
  • 1,489
  • 16
  • 31
  • 1
    Possible duplicate of [Shebang line limit in bash and linux kernel](https://stackoverflow.com/questions/10813538/shebang-line-limit-in-bash-and-linux-kernel) – Toby Speight Aug 22 '17 at 17:03
  • Possible duplicate indeed :) Except for the fact that my experiments show that the answer to that question is wrong. The claim is there is also 127. – Mark VY Aug 22 '17 at 17:07
  • 1
    I think that 127 is the *minimum* limit a POSIX platform can impose (and therefore the maximum you can *portably rely on*). The actual maximum for your platform is also mentioned in the answers to the duplicate - `BINPRM_BUF_SIZE` in Linux. – Toby Speight Aug 22 '17 at 17:09
  • 1
    How do you know it's not failing? If you run the script with Bash, and your `#!` is something like `/very/long/path/to/bash`, it may be silently failing without you knowing. – SnakeDoc Aug 22 '17 at 17:09
  • I am getting the correct output :) – Mark VY Aug 22 '17 at 17:09
  • 1
    What's the interpreter for your script? Is it something that your shell would execute (as SnakeDoc implies)? – Toby Speight Aug 22 '17 at 17:10
  • The interpreter is perl – Mark VY Aug 22 '17 at 17:12
  • BINPRM_BUF_SIZE is 128: https://github.com/torvalds/linux/blob/master/include/uapi/linux/binfmts.h – Mark VY Aug 22 '17 at 17:13
  • Is your script a perl script? – SnakeDoc Aug 22 '17 at 17:23
  • Yep, it's a perl script. The first part of the shebang line is the path to a perl interpreter. The rest is way too many command line arguments. – Mark VY Aug 22 '17 at 17:25
  • 1
    have you tried removing the shebang line and running the script anyway? does it work? – SnakeDoc Aug 22 '17 at 17:26
  • No, I have no tried that. I certainly can if you think I should, but it seems unlikely to work. For one thing, it's not the default perl interpreter on the machine, even assuming the computer magically figures out that it's Perl at all. For another thing, the command line arguments are rather important, and if guesses what they should be with the shebang line gone, I would be forced to assume the computer has psychic powers. – Mark VY Aug 22 '17 at 17:29
  • 1
    You can run it like `/path/to/your/perl yourscript.pl` and see the defaults. It may be truncating your shebang arguments is what I'm getting at, since you're over the max buffer size. Also, why not move your arguments into your script, if they're already in the file (in the shebang line), couldn't they be variables and avoid violating POSIX specs, or other, making your script more portable and more likely to work on other systems as well. – SnakeDoc Aug 22 '17 at 17:32
  • They are not the default. I learned this the hard way, because the script was failing until I added them. If you must know, they are there to modify the default module search path, because this system has a fairly perverse setup. (For good reasons I admit, but I still don't like it.) My goal is not to make the script more portable. My goal is find out why it's not already broken. – Mark VY Aug 22 '17 at 17:43
  • 1
    I figured it out. Perl was being too clever. I tried running another program with a long shebang line, and it simply got truncated. BUT!! Perl doesn't treat the shebang line as a comment. It parses its own shebang line! Oops. – Mark VY Aug 22 '17 at 17:51
  • 1
    @MarkVY, you should consider writing an answer to your question. – randomir Aug 22 '17 at 18:01
  • 2
    I doubt that Perl itself has any limit. – ikegami Aug 22 '17 at 18:07
  • 2
    Re "*The rest is way too many command line arguments.*", Why use the shebang line for that? You're literally passing values from the script to the script instead of just using them in the script in the first place! – ikegami Aug 22 '17 at 18:08
  • Because I want to modify the search path, which I think is traditionally done with the `-I` option. The alternative is to use `lib`, but how is that better? – Mark VY Aug 22 '17 at 18:09
  • 1
    @MarkVY It's "better" because it keeps the shebang line short and imposes no portability issues. – PerlDuck Aug 22 '17 at 19:37
  • @ikegami: indeed, perl itself probably doesn't have any limit; at first I didn't realize that perl had anything to do with this; I thought it was purely an OS issue. I never suspected that perl would go out of it's way to parse a comment! :) – Mark VY Aug 23 '17 at 17:06
  • 1
    Why not? The kernel does. – ikegami Aug 23 '17 at 17:17
  • Specifically *because* the kernel already (presumably) has done it, so perl has no need to do it again. (Of course, it turns out that perl does a much better job than the kernel in this case, but still.) – Mark VY Aug 23 '17 at 17:21

2 Answers2

3

Does the limit apply only to the executable path (which is under 100 chars in my case), or is there some strange magic at work?

The limit applies only to the executable path because there is strange magic at work. The strange magic goes by the name of Perl.

First, the limit of 127 characters is true. (Or maybe 128 or 126, didn't actually count.) Everything past that gets truncated. Second, regardless of whether there are spaces on the shebang line Linux will pass everything after the executable name as just ONE argument. Third, Perl will parse the shebang line and interpret it itself, which is why this was working. But note that the effect of all this is strange and a bit perverse. Suppose the shebang line looked like this:

#!/bin/perl -I/lib-one -I/lib-two

And suppose the truncation happened near the end, say, right before the "w" in "two" (that is, suppose the limit were 32 instead of 128, for ease of reading). Then the effect is as if you invoked perl at the command line as follows:

shell-prompt$ /bin/perl "-I/lib-one -I/lib-t" -I/lib-one -I/lib-two

Which "works" in this case, but in general won't.

Mark VY
  • 1,489
  • 16
  • 31
2

I know this doesn't answer your original question about the maximum #! line but I guess you rather have an XY problem.

Why don't you use lib? If you have hard coded include paths in your script (in your shebang line) anyway then you can as well denote them with use lib statements and keep the shebang line short:

#!/usr/bin/perl -some -absolutely -necessary -options

use lib '/lib-one';
use lib '/lib-two';
...
use lib '/lib-twenty-four';
PerlDuck
  • 5,610
  • 3
  • 20
  • 39
  • This will sound silly but... I don't want to "clutter" the source code with the idiosyncrasies of file paths on this system, which have no relevance to other systems. (The code is otherwise fairly portable. The tons of include directives are just to get LWP working.) But maybe this is the right approach after all. – Mark VY Aug 22 '17 at 20:40