Proper usr/bin/env ruby shebang


#1

I’m trying to convert some bash scripts to use /usr/bin/env ruby
instead of hardcoded shebang lines, and running into an issue. Using
this:

#!/usr/bin/env ruby -w

results in this error:

/usr/bin/env: ruby -w: No such file or directory

If I remove the -w, it runs and works fine. But of course, I want
the warnings check in there…

This works fine from the command line:

rsanheim@seekingalpha06a [/sa/bin]$ /usr/bin/env ruby -w
FOO = “hi”
FOO = “bye”
-:2: warning: already initialized constant FOO

Any ideas? Forgive me if I’m missing something obvious here…This is
red hat 4, I believe…

thanks,
Rob


#2

On 1/31/07, Rob S. removed_email_address@domain.invalid wrote:

If I remove the -w, it runs and works fine. But of course, I want
red hat 4, I believe…
Either you’re dating yourself, or you mean RHEL 4 … (I still have
manuals from both RHL 3 and 4 (and maybe install media if I look
hard enough))


#3

On 1/31/07, pat eyler removed_email_address@domain.invalid wrote:

Any ideas? Forgive me if I’m missing something obvious here…This is
red hat 4, I believe…

Either you’re dating yourself, or you mean RHEL 4 … (I still have
manuals from both RHL 3 and 4 (and maybe install media if I look
hard enough))

You’re right, I meant RHEL4.

  • rob

#4

On Thu, 1 Feb 2007, Rob S. wrote:

If I remove the -w, it runs and works fine. But of course, I want
red hat 4, I believe…

thanks,
Rob

harp:~ > cat a.rb
#!/usr/bin/env ruby -w
p $VERBOSE
FOO = 42 and FOO = 42

harp:~ > ruby a.rb
true
a.rb:3: warning: already initialized constant FOO

harp:~ > ruby -v
ruby 1.8.4 (2005-12-01) [i686-linux]

harp:~ > uname -srm
Linux 2.4.21-47.0.1.EL i686

harp:~ > cat /etc/redhat-release
Red Hat Enterprise Linux WS release 3 (Taroon Update 8)

what happens for you?

-a


#5

Hi,

At Thu, 1 Feb 2007 01:45:15 +0900,
Rob S. wrote in [ruby-talk:237036]:

I’m trying to convert some bash scripts to use /usr/bin/env ruby
instead of hardcoded shebang lines, and running into an issue. Using
this:

#!/usr/bin/env ruby -w

results in this error:

/usr/bin/env: ruby -w: No such file or directory

Do not rely on /usr/bin/env, it may not exist.

#!/bin/sh
exec ruby -x “$0” “$@”
#!ruby -w


#6

On 1/31/07, Nobuyoshi N. removed_email_address@domain.invalid wrote:

results in this error:

/usr/bin/env: ruby -w: No such file or directory

Do not rely on /usr/bin/env, it may not exist.

#!/bin/sh
exec ruby -x “$0” “$@”
#!ruby -w

Ugh, so I need that at the top of all these scripts? I thought
/usr/bin/env was the ‘better’ way to go?


#7

On 1/31/07, removed_email_address@domain.invalid removed_email_address@domain.invalid wrote:

ruby 1.8.4 (2005-12-01) [i686-linux]
-a

Hmm, so that works – the issue is where I run it as an executable
(see the end of the log)

sa [~]$ ruby a.rb
true
a.rb:3: warning: already initialized constant FOO

sa [~]$ ruby -v
ruby 1.8.5 (2006-12-25 patchlevel 12) [i386-linux]

sa [~]$ uname -srm
Linux 2.6.9-42.0.3.ELsmp i686

sa [~]$ cat /etc/redhat-release
Red Hat Enterprise Linux ES release 4 (Nahant Update 4)

sa [~]$ chmod +x a.rb

sa [~]$ ./a.rb
/usr/bin/env: ruby -w: Permission denied

  • Rob

#8

On Thu, 1 Feb 2007, Rob S. wrote:

Ugh, so I need that at the top of all these scripts? I thought
/usr/bin/env was the ‘better’ way to go?

you can use

#! /usr/bin/env ruby
$VERBOSE=true

-a


#9

ara.t.howard:

harp:~ > cat a.rb
#!/usr/bin/env ruby -w
p $VERBOSE
FOO = 42 and FOO = 42

harp:~ > ruby a.rb
true
a.rb:3: warning: already initialized constant FOO

There’s no shell or anything here interpreting the shebang.

Kalman


#10

On 1/31/07, removed_email_address@domain.invalid removed_email_address@domain.invalid wrote:

#!ruby -w

Ugh, so I need that at the top of all these scripts? I thought
/usr/bin/env was the ‘better’ way to go?

you can use

#! /usr/bin/env ruby
$VERBOSE=true

That will work - thanks.


#11

On 1/31/07, Rob S. removed_email_address@domain.invalid wrote:

this:
exec ruby -x “$0” “$@”
$VERBOSE=true

That will work - thanks.

My hosting provider provided this very helpful post on this whole mess:

http://elliotth.blogspot.com/2006/04/lesson-about-using-env1-in-script.html

Which explains why passing in -w wasn’t working, and why just setting
$VERBOSE to true isn’t the same thing. Seems like it shouldn’t be
this hard to get a cross platform script working, with warnings.

  • Rob

#12

On Thu, Feb 01, 2007 at 02:20:38AM +0900, Rob S. wrote:

Ugh, so I need that at the top of all these scripts? I thought
/usr/bin/env was the ‘better’ way to go?

This issue has come up before (see [ruby-talk:27508]). However, Austin
Ziegler pointed out in [ruby-talk:56340] that the sh/exec solution won’t
work on non-Unix environments. See also ‘perldoc perlrun’ for more
discussion on the issue (ruby takes much of its behavior from perl in
this case).

Paul


#13

On Jan 31, 2007, at 08:45, Rob S. wrote:

If I remove the -w, it runs and works fine. But of course, I want
the warnings check in there…

Linux’s env/shebang is broken, so you can’t use the shebang this
way. It decides “ruby -w” is the name of the thing you want to
lookup, and of course env can’t find that because there isn’t one.


#14

On 31 ene, 16:53, Paul B. removed_email_address@domain.invalid wrote:

Paul
All solutions posted so far are broken in one way or another.

What will work across platforms and OSes is this:

#! /usr/bin/env ruby

And add:

export RUBYOPT="-w $RUBYOPT"

to your environment (.bashrc) or:

setenv RUBYOPT “-w $RUBYOPT”

for cshrc, tcsh (.cshrc, .tcshrc, etc). For windows, do:

set RUBYOPT="-w %RUBYOPT%"

in a bat file (or in your environment variables for the user or the
machine).
The additional benefit of this is that you will not only get your
little script compiled with warnings on, but every piece of ruby code
you run, too.
Also, if you need performance, you can easily turn off the -w flag,
without having to modify a single file.


#15

On Thu, Feb 01, 2007 at 01:45:15AM +0900, Rob S. wrote:

Any ideas?

I tend to do:

#!/usr/bin/env ruby
BEGIN {$VERBOSE = true}

as I think that’s the best you can do within a single script. If the
link referenced in another reply is correct, then warnings won’t be
emitted as the script initially loads. However, doing a manual “ruby -w
foo_script.rb” once to test the code should catch any of these warnings.


#16

On Thu, Feb 01, 2007 at 08:35:08AM +0900, gga wrote:

What will work across platforms and OSes is this:

#! /usr/bin/env ruby

This will not work for platforms that put env in /bin or don’t have /usr
mounted.

Paul


#17

On 1/31/07, Eric H. removed_email_address@domain.invalid wrote:

If I remove the -w, it runs and works fine. But of course, I want
the warnings check in there…

Linux’s env/shebang is broken, so you can’t use the shebang this
way. It decides “ruby -w” is the name of the thing you want to
lookup, and of course env can’t find that because there isn’t one.

This is not the fault of Linux. It’s an unavoidable consequence of the
way
the shebang-line is defined in various standards. In fact, I’m the guy
who
fixed FreeBSD to comply with those standards, and thus I deliberately
changed the way FreeBSD handled shebang lines from “convenient” to
“broken”. For reasons which might not be intuitively obvious, the
broken
behavior is required.

Since FreeBSD used to process the shebang line in a more convenient
way, I also came up with some changes to /usr/bin/env which can be used
to recreate the more convenient problem. However, those new options are
only available on FreeBSD (afaik).

I also have to write ruby or perl scripts which have to work on a
variety of
unix-based operating systems. What I have come up with is the
following.
I’m sure that it will not work on some operating system, but it works on
the
dozen operating systems that I have to care about, in all situations
that I
have cared about.

#!/bin/sh

-------±--------±--------±------- +

--------±--------±--------±--------+

/ This section is a safe way to find the interpretter for ruby,

\

| without caring about the user’s setting of PATH. This reduces

|

| the problems from ruby being installed in different places on

|

| various operating systems. A much better solution would be to

|

| use /usr/bin/env -S-P' , but right now-S-P’ is available

|

\ only on FreeBSD 5, 6 & 7. Garance/2005

/
OSRUBYBIN=
for fname in /usr/local/bin /opt/csw/bin /opt/local/bin /usr/bin ; do
if [ -x “$fname/ruby” ] ; then OSRUBYBIN="$fname/ruby" ; break; fi
done
if [ -z “$OSRUBYBIN” ] ; then
echo “Unable to find a ‘ruby’ interpretter!” >&2
exit 1
fi

eval ‘exec “$OSRUBYBIN” -x -S $0 ${1+"$@"}’
echo “The ‘exec “$OSRUBYBIN” -x -S …’ failed!” >&2
exit 1
#! This #!-line starts the real script, due to the marker: ruby
…[ and then the first line of the real ruby script]…

Obviously you could add the ‘-w’ after ‘-x’ on the eval/exec line, if
you
also wanted that option. And if you do something weird like install
‘ruby’ in /bin (so that you can find out when /usr is not mounted), then
you’d need to add that to the list of directories which are searched.

In some cases, I also set a new value for PATH= in the /bin/sh
portion of the script, to avoid ruby’s warning about an “Insecure
world writable dir”. That warning message can also be avoided
by setting $VERBOSE in the ruby script, but in some cases it’s
just easier for me to change the value for PATH.

I suspect that all this is too esoteric for most people to other with!
:slight_smile:
It really is rather absurdly complicated to get 100% right in 100% of
the situations that every ruby script might be run in.


#18

Paul B. wrote:

On Thu, Feb 01, 2007 at 08:35:08AM +0900, gga wrote:

What will work across platforms and OSes is this:

#! /usr/bin/env ruby

This will not work for platforms that put env in /bin or don’t have /usr
mounted.

Some platforms don’t even have an env. I regularly work on one.

  • Will

#19

On Fri, 2 Feb 2007, Garance A Drosehn wrote:

for fname in /usr/local/bin /opt/csw/bin /opt/local/bin /usr/bin ; do
#! This #!-line starts the real script, due to the marker: ruby
by setting $VERBOSE in the ruby script, but in some cases it’s
just easier for me to change the value for PATH.

I suspect that all this is too esoteric for most people to other with! :slight_smile:
It really is rather absurdly complicated to get 100% right in 100% of
the situations that every ruby script might be run in.

thanks garance! i’m filing this under ‘definitive’ in my mail :wink:

-a


#20

On 2/1/07, Paul B. removed_email_address@domain.invalid wrote:

On Thu, Feb 01, 2007 at 08:35:08AM +0900, gga wrote:

What will work across platforms and OSes is this:

#! /usr/bin/env ruby

This will not work for platforms that put env in /bin or don’t have /usr
mounted.

Well, on many of my systems, if /usr is not mounted, then ‘ruby’ itself
is also not available! :slight_smile:

I have a bigger concern with using /usr/bin/env for this. The
/usr/bin/env trick will only work if ruby IS in the PATH of the
person who is running the ruby script, and if that version of ruby is
the version expected by the script. On many systems that is a safe
assumption, but it isn’t always true.

Consider something like MacOS 10, for instance, where Apple
ships one version of ruby in /usr/bin, but many people will install a
newer version in /opt/local/bin. I’ve had some scripts fail because
the user running them didn’t have /opt/local/bin in their PATH.

(ie, I helped them install ruby into /opt/local/bin using macports,
but they didn’t update their settings for PATH)