how to write a ruby script running on different system - ruby

I have a ruby script, which declare the ruby path in the first line
#! /usr/bin/ruby
But, I need it to be run in different system. And the path of Ruby are different in different system. How to handle this issue?

In unix systems you can get away with
#! /usr/bin/env ruby
This has the effect of using the ruby found on the path. env is a core binary on pretty much every unix.

Related

Ruby script: shebang with absolute path to ruby not working

I am using Mac OS X. I have two versions (2.1.5 and 2.0.0) of Ruby installed. The former installed at /another/.path/to/ruby (there is a dot before "path" to mimic the fact that the path contains a dot-headed directory in between), in addition to the default system one (version 2.0.0) at /usr/bin/ruby. I used rbenv to install Ruby.
After I manually set the PATH environment variable so the default ruby command will be found in another directory: /another/.path/to/ruby. Now I check
which -a ruby
It is using correct ruby first, as output.
/another/.path/to/ruby
/usr/bin/ruby
Now I create a script, rbs, with the first line of shebang specifying the ruby to use.
#!/usr/bin/env ruby
puts 'hey there'
Then I run
./rbs
it outputs 'hey there'. Good. Meanwhile, the Ruby is using the correct version.
/usr/bin/env ruby --version
as well as
ruby --version
both output 2.1.5. So it does great job to use the new version.
However, here is where the problem occurs: now I update rbs file to be:
#!/another/.path/to/ruby
puts 'hey there'
Note that I updated the shebang to use the absolute path to the desired ruby. then I run
./rbs
It outputs:
./rbs: line 2: puts: command not found
which is too weird;
but if I run
ruby ./rbs
it outputs 'hey there' as normal. It looks like the shebang works perfect using /usr/bin/env ruby, but not for absolute path for the newly install ruby?
Why is this? Is there a way to fix it so the updated script can still work by typing the following?
./rbs
Thanks!
The puts: command not found message indicates that your script is not being run by Ruby, but by the shell instead. So first, I would double-check your shebang line's syntax and path.
Second, note that rbenv uses shims that dynamically find and run the right version of ruby (and associated programs like gem, etc). But the shims are scripts, and scripts can't themselves be shebang interpreters; you have to find and use the actual path to the ruby executable (as output by rbenv which ruby).
On the other hand, since /usr/bin/env is an executable, you can always use something like #!/usr/bin/env ruby, which will work even if the ruby it finds in the path is itself a script.
I can't comment, (otherwise I'd add as a comment) but I think its worthwhile to add that the
#!/usr/bin/env ruby
MUST be the first line of the file. This tripped me up for a while.
source

ZSH Ruby command not found

I'm pretty inexperienced with terminal type stuff besides the most basic commands, I recently switched from Bash to ZSH with in oh-my-zsh. I'm trying to make an executable ruby script at usr/bin/test.rb. For what it's worth, I never tried this with bash so I have no idea if its zsh specific.
$~ test.rb
/usr/bin/test.rb: line 2: puts: command not found
$~ ruby test.rb
ruby: No such file or directory -- test.rb (LoadError)
and my .zshrc file:
export ZSH=$HOME/.oh-my-zsh
source $ZSH/oh-my-zsh.sh
export PATH="/Users/jason/.rvm/gems/ruby-2.0.0-p247/bin:/Users/jason/.rvm/gems/ruby- 2.0.0-p247#global/bin:/Users/jason/.rvm/rubies/ruby-2.0.0-p247/bin:/Users/jason/.rvm/bin:.git/safe/../../bin:.git/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin:/Users/jason/.rvm/bin"
.
~ which ruby
/Users/jason/.rvm/rubies/ruby-2.0.0-p247/bin/ruby
test.rb
#!/usr/bin/env ruby
puts 'test!'
$~ test.rb
/usr/bin/test.rb: line 2: puts: command not found
This is probably because your script is missing an essential line, often called a "pound-bang line" or, more simply, a "bang line", which tells the operating system what program to use to execute the rest of the file. Typically, for Ruby scripts, it looks like:
#!/usr/bin/ruby
or
#!/usr/bin/env ruby
and MUST be the first line in the file. When the OS opens the file, it looks for #! and, if it sees those, launches the executable at the path given, and passes the script to it. That's basic script execution on a *nix system, and applies to sh/Bash/Perl/Python/Ruby and any number of other executable applications on a *nix system.
ruby test.rb
ruby: No such file or directory -- test.rb (LoadError)
I suspect the second failed because you weren't in the /usr/bin/ directory when you executed that command. Ruby tried to run the script but couldn't find it in the local/current directory.
I'm not trying to be cruel, but, as a programmer, you'll spend a huge amount of time at the command-line, especially so if you are programming in C/C++, Perl, Ruby, Python, or any non-IDE based language. You have to learn how the OS works otherwise disasters of varying sizes and shapes await you, so, in parallel to learning a language you need to learn how to use, and administer, your OS. You don't have to be a power-user or administrator, but you have to know enough to understand good instructions from ones that don't apply, or are just plain-wrong.
Well I was facing the same problem, I had ruby & rails installed but I couldn't run them on ZSH
The answer is so simple
Just Add the following lines to .zshrc
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
Then run
source ~/.zshrc
After that to check if ruby & rails are found by ZSH run
ruby --version
rails --verison

ruby script specific gemset backick

We have a rails sidekiq setup to run jobs.
I am trying to make a job as portable as possible by separating the actual script from the sidekiq call.
So sidekiq calls a small stub job that backtick calls the actual script and captures the output.
That part works fine. But sidekiq runs the job as root, rather than as the user who's environment has all the rvm parts, rubies, and gemsets. I'd like to use the existing user rvm rubies and gemsets.
in the calling script (sidekiq job):
output = `source /path/to/dudes/rvm/environment.file && rvm use \
2.0.0-pxxx#default do ruby /path/to/actual/script.rb`
and the called script gets run, but as root and it obviously doesn't work as I intended because my requires are not found.
If I take that same command string and run it as a local user from BASH, who also has no gemsets, it seems to work.
I've tried just backtick calling it like a shell script
output = `/path/to/actual/script.rb`
...and in the called script, various combinations of shebangs.
#!/usr/bin/env ruby
#!/usr/bin/env rvm use everything i found on the internets
Now, I've gotten ruby scripts to run in environments with linux upstart jobs by using bash script wrappers like this:
http://techhelplist.com/index.php/tech-tutorials/43-linux-adventures/85-upstart-ruby-job-with-rvm
But I am trying to find a way to do this with no wrappers. Is it possible?
No, it is not possible.
When you use the "backtick" operator you are essentially calling Kernel#system(...). This means the command you execute is run in a subshell which cannot change the environment of the parent process in the ways you want.
See this question for comparison: How to run code after ruby Kernel.exec
Also consider reading more about the UNIX process model.
According to Upstart Intro, Cookbook and Best Practises, point 4.2.2, you can set user jobs in $HOME/.init/.

RVM | Running user scripts

Is it possible while using the Ruby version manager to run scripts not from the console but using other ways — at system startup or by a keyboard shortcut for example?
RVM installs a command rvm-shell. You can use rvm-shell, pass it whatever you would pass rvm use, then you can execute a shell command.
rvm-shell will set your environment for that shell script, or you can use rvm-shell on one line, and have it execute the parameter as a shell command.
For example:
rvm-shell rbx-2.0 -c 'which ruby'
Which should equal your rbx ruby.
It'd help to know the system, but the answer is yes, though you'd need to either know which is the current directory, or set the system ruby to be the one you needed for these scripts (especially startup). You might also need to experiment, as it would depend at which point in the startup you needed the scripts to run, but you can probably get more answers on that from the irc rvm channel.
rvm default do /path/to/ruby/script

Preferred way of #! in shell scripts

I searched google but couldn't find an answer to this rather simple question. I have a python script that has the hash-bang (#!) on the first line:
#!/usr/bin/python
However, what if this is run on a computer with python in /bin/python or /usr/local/bin/python, or some other place? There has to be a better way to set the interpreter for a shell script. It should be possible to set it via $PATH, as that will know where to find python if it's installed on the system.
Use env.
#!/usr/bin/env python
It's not bulletproof, but it covers more cases than /usr/bin/python.
Use
#!/usr/bin/env python
env is virtually always in /usr/bin, and will execute any program in the PATH.
Some people prefer to start with:
#!/usr/bin/env python
Not sure that this is a vast improvement as you're now assuming that python is in the path and that it's the right version, but it's an option.

Resources