proper usr/bin/env ruby shebang

R

Rob Sanheim

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
 
P

pat eyler

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...

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))
 
R

Rob Sanheim

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...

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
 
A

ara.t.howard

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

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
 
N

Nobuyoshi Nakada

Hi,

At Thu, 1 Feb 2007 01:45:15 +0900,
Rob Sanheim 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
 
R

Rob Sanheim

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
--

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
 
R

Rob Sanheim

Hi,

At Thu, 1 Feb 2007 01:45:15 +0900,
Rob Sanheim 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

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

Kalman Noel

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
 
A

ara.t.howard

Hi,

At Thu, 1 Feb 2007 01:45:15 +0900,
Rob Sanheim 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

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
 
R

Rob Sanheim

Hi,

At Thu, 1 Feb 2007 01:45:15 +0900,
Rob Sanheim 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

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.
 
R

Rob Sanheim

Hi,

At Thu, 1 Feb 2007 01:45:15 +0900,
Rob Sanheim 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


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.

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
 
E

Eric Hodel

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...

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.
 
P

Paul Brannan

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
 
G

gga

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

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.
 
M

Mike Kasick

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.
 
P

Paul Brannan

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
 
W

Will Parsons

Paul said:
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
 
G

Garance A Drosehn

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! :)
It really is rather absurdly complicated to get 100% right in 100% of
the situations that every ruby script might be run in.
 
A

ara.t.howard

#!/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! :)
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 ;-)

-a
 
G

Garance A Drosehn

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! :)

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)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,828
Latest member
LauraCastr

Latest Threads

Top