Using shebang with rvm?

What would be the appropriate path to use after a shebang in the first
line of a ruby source, if I want to use the currently active rvm
version of Ruby?

I am currently using rvm 1.17.3

I hope it doesn’t matter, but just in case I am on Mountain Lion.

Its no different with RVM than without. RVM is just a set of scripts
that downloads, compiles and installs various rubies for you. It also
makes gem sets as well. The gem sets are just symlinked directories. RVM
then sets the GEM_HOME, RUBY_HOME, and various shell variables that Ruby
normally reads.

This means that once you install Ruby via RVM and tell it which one you
want to use, it sets the vars and its done. After that its all Ruby
itself. So, to answer your question, you would use #!/usr/bin/env as the
first line.

D. Deryl D.

“The bug which you would fright me with I seek” - William Shakespeare -
The Winter’s Tale, Act III, Scene II - A court of Justice.

he means
#!/usr/bin/env ruby

Correct. My apologies.

#!/usr/bin/env ruby


D. Deryl D.

“The bug which you would fright me with I seek” - William Shakespeare -
The Winter’s Tale, Act III, Scene II - A court of Justice.

Thanks, but most shebang files I have seen include an absolute path to
the language interpreter. Rvm does not intervene when the shell is
interpreting a script containing a shebang. So, for example, if you
create this script on OS 10.8 it returns 1.8.7 no matter what version
you have selected in rvm.

$ cat tryshbang.rb
#! /usr/bin/ruby
puts RUBY_VERSION
$ ./tryshbang.rb
1.8.7
$

I have since found the following recommendation in the Wikipedia article
on shebang: http://en.wikipedia.org/wiki/Shebang_(Unix)

#! /usr/bin/env ruby
puts RUBY_VERSION

It works.

Of course, because you use a FULL path. By not using #!/usr/bin/env ruby
(notice the /usr/bin/env part) you’re specifically calling a specific
ruby which bypasses ALL environment variables and uses the direct
binary. No one told you to use #!/usr/bin/ruby. They said #!/usr/bin/env
ruby which tells the script to query the path for the first ruby found
and use its environment vars, and to make its exit code status be the
return value of the script itself, when its done executing. (See man
env)


D. Deryl D.

“The bug which you would fright me with I seek” - William Shakespeare -
The Winter’s Tale, Act III, Scene II - A court of Justice.

This is the difference.

https://gist.github.com/4386008


D. Deryl D.

“The bug which you would fright me with I seek” - William Shakespeare -
The Winter’s Tale, Act III, Scene II - A court of Justice.

It’s primarily for portability. Using env more or less defeats
portability issues as every box could have ruby installed somewhere
else. For example rvm really is just a environment hack.

When you call a program, in this case ruby, with env your shell will
locate the first ruby it finds in the path. This is just a hashed
lookup table for speed. Basically when you call for example % ruby
program.rb it expands to (say on my system) % /usr/local/bin/ruby
/path/to/my/program.rb – of course rvm takes precedence over the
system paths as that’s what the utility was designed to do.

A common mistake, which your observing, is where a direct path is
used; the programmer does not take into account that different
operating systems put their binaries in different directories.

Always use env. Any of the absolute paths which you see are usually
from uninformed dilettantes or users whom want world domination for
their tools or OSes and are throwing a fit by forcing any of their
users to write a small sed script to patch their install.

If you would like to see your paths hash you can simply type in the
command hash at the prompt. If you need to update your hash you can
use the -r option. If you would like to know more, outside of the web
wiki, read the ash (not bash) man page: http://man.freebsd.org/sh

Quote:
hash [-rv] [command …]
The shell maintains a hash table which remembers the
locations of
commands. With no arguments whatsoever, the hash command
prints
out the contents of this table. Entries which have not
been
looked at since the last cd command are marked with an
asterisk;
it is possible for these entries to be invalid.

         With arguments, the hash command removes each specified 

command
from the hash table (unless they are functions) and then
locates
it. With the -v option, hash prints the locations of the
com-
mands as it finds them. The -r option causes the hash
command to
delete all the entries in the hash table except for
functions.

~Stu

Stu wrote in post #1090776:

It’s primarily for portability. Using env more or less defeats
portability issues as every box could have ruby installed somewhere
else.

Thanks, Stu, the entire note was very helpful.

I am not sure if you are suggesting that I should also be able to have a
non-absolute path to env command.

Using bash on OS 10.8 I find that a she-bang for Ruby just doesn’t work
unless it points to some absolute path.

The most portable I can make a file is to say

     #! /usr/bin/env ruby

Anyway, that approach meets my needs.

Regards,

Wes


"With consistency a great soul has simply nothing to do. Speak what you
think today in hard words and tomorrow speak what tomorrow thinks in
hard words again, though it contradict everything you said today. "

                       Ralph Waldo Emerson

Wes ~

That is what I was saying. Also this is correct if you deviate from
any posix syntax or use a third party language. So env would also be
used for bash or zsh where bashisms( i.e. shell extension) are used
but not ash.

example to use bash it’s the same semantically for portability if one
requires bash or zsh specific syntax:

#!/usr/bin/env ksh
#!/usr/bin/env bash
#!/usr/bin/env zsh
#!/usr/bin/env fish

All bourne derived shells( i.e. not csh) are backward compatible with
posix sh which is a small mixture of original bourne syntax and korn
syntax.

The only time you would ever want to use a direct path is with a posix
sh script as so:

#!/bin/sh

or csh … but don’t use csh =)

#!/bin/csh -f

If your really curious on the spec you can be read here:
http://rubyprogrammer.net/~stu/posix/

You can set your path inside your interactive rc file with the $PATH
variable. It’s delimited with a colon and is a first positive match
wins hash. If your writing a script that depends on knowing where your
binaries are you can use a variable to hold the direct path to the
executable or set the path variable directly inside the script.

Trivial example of embedded ruby embedded inside shell:

#!/bin/sh
r=/path/to/mri/ruby20
$r <<EOF
puts “Hello, world!”
RbConfig::CONFIG.each_pair { |k,v| puts k+’:<=>:’+v }
s=RbConfig::CONFIG.values.grep /bin/*sh/
puts <<EOR
Bye bye your current shell is #{s}
Your ruby is ${r}
EOR
EOF

Set the execute bit and run it through a pipe to less or tail -2 for
example. Have another ruby. Wanna glue one to the other? Create
benchmark results? Just some ideas. Maybe not the most practical
examples but provide you some insight on what may be useful with a
couple lines of shell code.

Bash is an okay shell for beginners. Consider zsh for interactive use
as it has a nice flow to development once you begin to customize it. I
have ash on FreeBSD which is very fast for shell scripts as it’s <70kb
binary in contrast to bash being over a meg. I don’t believe they
ported Almquist’s shell to OSX. Maybe homebrew has it (sometimes under
the name dash in the gnu distros so I’m unsure what got ported on osx
as it’s a mashup of FreeBSD kernel with BSD, next and gnu userland)…

My main toolset preference tends to be sh for system level automata,
primarily because that is my background… consider scripting a
network where ruby may or may not be present machine to machine , ruby
for larger stack oriented projects where oops, arrays may be needed,
zsh, vi, irb for my preferred development stack.

I also use rvm which is one of the few bash specific scripts, actually
I would call rvm a framework utility at this point, which it is obvious
where
posix was considered but the need for the automation on directory
switching with rvmrc for developers whom needed various sandboxing
with minimal setup usurped avoiding the extended syntax of bash. The
need for arrays also is where bash becomes the dependency.

Take a look at Wayne’s code. You will see some of the best shell code
by someone who takes such things seriously by studying rvm.

Other projects of the same vein such as chruby or rbenv make no effort
for portability outside of forcing user to install bash or run a
computer only capable of supporting homebrew .

I do find it ironic how the author of rbenv promoted it initially with
sort of a dunning kruger style marketing his way was the “one true
way” when it’s far from a minimalist’s alternative to rvm while
deviating from posix for no reason other than it’s obvious the rbenv
developer is not a system administrator and knows of nothing other
than how to provide FUD with ad hominem bullet points like his lamers
statement that rvm is dangerous and error-prone. I guess this sort of
thing is how people get themselves noticed when either vying for some
corporate employment contract or simply to gain some sort of
superficial notoriety.

On a simpler level consider command env to work like how you
understand how the ruby interpreter yields results from it’s block
iterators. /usr/bin/env ruby basically has ruby as an argument to the
command env which locates ruby in the path hash and yields the result
which in this case is the path located to the shell which instructs
the kernel to create a memory overlay to load ruby after env evaluates
the ruby location; From there ruby will be executed in place in order
to evaluate any of the code after which in turn yields each token to
the executable. The env will work with any command hashed from the
$PATH global environment variable.

Happy Hacking.

~Stu

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs