72

I've got a simple script:

#!/usr/bin/env ruby --verbose
# script.rb
puts "hi"

On my OSX box, it runs fine:

osx% ./script.rb
hi

However, on my linux box, it throws an error

linux% ./script.rb
/usr/bin/env: ruby --verbose: No such file or directory

If I run the shebang line manually, it works fine

linux% /usr/bin/env ruby --verbose ./script.rb
hi

But I can replicate the error if I pack ruby --verbose into a single argument to env

linux% /usr/bin/env "ruby --verbose" ./script.rb
/usr/bin/env: ruby --verbose: No such file or directory

So I think this is an issue with how env is interpreting the reset of the shebang line. I'm using GNU coreutils 8.4 env:

linux% /usr/bin/env --version
env (GNU coreutils) 8.4
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Richard Mlynarik and David MacKenzie.

This seems really odd. Is this a common issue with this version of env, or is there something else going on here that I don't know?

3
  • 5
    relevant?
    – rampion
    Feb 6, 2013 at 20:21
  • Same here with coreutils 8.17. Weird. Reporting to Fedora, as this goes explicitly against what the manual says.
    – vonbrand
    Feb 6, 2013 at 20:32
  • @vonbrand What did Fedora say? "We don't care."
    – cat
    May 1, 2016 at 12:43

3 Answers 3

63

Looks like this is because Linux (unlike BSD) only passes a single argument to the shebang command (in this case env).

This has been extensively discussed on StackOverflow.

5
  • 3
    see also this page for a review of the behaviour on different Unices. Feb 6, 2013 at 20:46
  • 4
    Specification fail. My god. Dec 4, 2014 at 17:09
  • 3
    If by "specification fail" you mean all Unix systems should accept more than 1 argument, then I 100% agree with you :) Mar 25, 2017 at 0:01
  • 1
    Not so much 'linux' as GNU.
    – will
    Jul 26, 2019 at 1:37
  • 1
    @will not really GNU, the shebang is parsed by Linux
    – Ruslan
    Nov 27, 2021 at 8:55
7

Found this via @rampion comment:

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.

Source: http://lists.gnu.org/archive/html/bug-sh-utils/2002-04/msg00020.html

7

Coreutils>=8.30:

#!/usr/bin/env -S ruby --verbose

The -S or --split-string env option is documented in the GNU coreutils manual (see: info '(coreutils) env invocation' or the online manual). Below is an excerpt:

Most operating systems (e.g. GNU/Linux, BSDs) treat all text after the first space as a single argument. When using env in a script it is thus not possible to specify multiple arguments.

In the following example:

#!/usr/bin/env perl -T -w print "hello\n";

The operating system treats perl -T -w as one argument (the program's name), and executing the script fails with:

/usr/bin/env: 'perl -T -w': No such file or directory

The -S option instructs env to split the single string into multiple arguments. The following example works as expected:

$ cat hello.pl
#!/usr/bin/env -S perl -T -w print "hello\n";

$ chmod a+x hello.pl $ ./hello.pl hello

and is equivalent to running perl -T -w hello.pl on the command line prompt.

3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.