bug-sh-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: env won't accept arguments in shebang


From: Bob Proulx
Subject: Re: env won't accept arguments in shebang
Date: Fri, 19 Apr 2002 23:55:32 -0600

> I'm not 100% sure this is a bug, but I can't find an explanation for this
> behavior in either the env texinfo file or on the sh-utils FAQ page.  If
> you run this command from the shell prompt:
> 
>       echo 'print "foo\n"' | /usr/bin/env perl -w
> 
> env works as expected. However, the corresponding perl script:
> 
>       #!/usr/bin/env perl -w
>       print "foo\n"
> 
> returns the following error:
> 
>       /usr/bin/env: invalid option --  
>       Try `/usr/bin/env --help' for more information.
> 
> This is true for pretty much any command which is passed an argument. It
> works fine from the prompt, but simply won't work on a shebang line. Is
> this expected behavior? If so, why?

Thank you for your report.  However, you are confusing the operating
systems actions with those of env.  What you are seeing is not a bug
in env but a limitation of the operating system.  The env command can
take many arguments.  But the #!interpreter syntax may only take one.
Everything after the interpreter is passed as a single argument.

I just answered an almost identical question in another message and I
wonder if perhaps the coincidence of two people asking this question
at the same time is not really a coincidence at all.

The quick summary is that #! in the operating system kernel only
allows exactly zero arguments or exactly one argument but not more.

The #! syntax is generally called the Berkeley #! hack.  It was a
wonderful improvement over not having it at all.  But is still
considered a hack because it has many limitations.  One is that only
one argument is allowed.  Some operating systems have a limit of not
more than 32 characters for the line allowed.  Another is that it must
be a binary program and not another shell interpreter. These have
nothing to do with the 'env' command itself.  You may substitute any
command there such as my favorite which is 'echo' and you will see the
same limitation imposed by the underlying operating system.

It is the same as if you had said the following and passed the two
things as one thing to env.  Env is not a shell and does not split
arguments on white space or quoting.  You would need to use a shell
for that.

  env 'perl -w'
  env: perl -w: No such file or directory

W. Richard Stevens documents this best in Advanced Programming in the
UNIX Environment.  The HP-UX man pages document this in the 'man exec'
page.  Most basic shell programming texts should document this when
talking about the #! line.  The Programming Perl "camel" book
documents this but gets the details wrong which you will find if you
experiment with it and I won't detail that here.  You did not say or I
did not see which operating system you were running on and therefore I
cannot suggest where that might be documented on your system.  The
possibilities are large and my experience is limited.

What happens is that the kernel processes the first two characters of
the file looking for #!.  If those are found then it skips all space
characters looking for a non-space character and extracts the
interpreter path which must be a real executable and not another
script, although linux extends that to allow recursive script
processing.  Having found that then it skips to the first non-space
character where it takes from there to the next newline character and
passes that as a single argument to the command.  There is no 'shell'
processing of quotes or other meta characters.  It is all very simple
and brute force.  Therefore you cannot get fancy with options there.
You get exactly one argument white space included and 'perl -w' is
what the kernel sees here and passes on.

As a workaround you may use the perl '$^W = 1;' syntax in the script
to turn on warnings as if the -w option had been passed in as an
option.

Hope that answers your question.

Bob



reply via email to

[Prev in Thread] Current Thread [Next in Thread]