Moving ruby and rubygems into a custom path - ruby

I have a local ruby interpreter created a third party which is installed under /usr/lib/projectA/ruby/bin/ruby
Now, I want to copy the whole folder strcuture into another folder with the same structure: /usr/lib/projectB/ruby/bin/ruby
After I copied the files, and call the copied ruby, e.g.
# /usr/lib/projectB/ruby/bin/ruby -v
ruby 1.9.x
Seems to be working, however, when I run
# /usr/lib/projectB/ruby/bin/ruby -e 'puts 1'
<internal:gem_prelude>:1:in `require': cannot load such file -- rubygems.rb (LoadError)
from <internal:gem_prelude>:1:in `<compiled>'
Seems it can't find the rubygems, so I add the path
# /usr/lib/projectB/ruby/bin/ruby -e 'puts 1' -I '/usr/lib/projectB/ruby/lib/'
/usr/lib/projectB/ruby/lib/ruby/1.9.1/rubygems.rb:31:in `require': cannot load such file -- rbconfig (LoadError)
Now, another files cannot be loaded, so I assume more to come..
So
What is the correct method to set the new rubygems base path for my new ruby?
Why even calling puts 1 will invoke the rubygems?
p.s. I can't use rvm or similar approach as we need to deploy the whole zip package with the ruby to our user.

You can use RVM and set the path in your .rvmrc file via rvm_path parameter.
Also double check your ~/.bashrc or ~/.bash_profile if the paths are OK.
Other option is to play with $PATH and $LD_LIBRARY_PATH for ruby and use $GEM_PATH which provides the locations (there may be several) where gems can be found.
You probably will need to play with Ruby's environmental variables:
RUBYOPT Additional command-line options to Ruby; examined after real command-line options are parsed ($SAFE must be 0).
RUBYLIB Additional search path for Ruby programs ($SAFE must be 0).
RUBYPATH With -S option, search path for Ruby programs (defaults to PATH).
RUBYSHELL Shell to use when spawning a process; if not set, will also check SHELL or COMSPEC.
DLN_LIBRARY_PATH Search path for dynamically loaded modules.
RUBYLIB_PREFIX (Windows only) Mangle the RUBYLIB search path by adding this prefix to each component.
from here.

Related

How to make a Ruby file (in a gem) executable from anywhere like a regular command?

I have a command in my gem: bin/tennis. Currently to execute it you have to cd into the gem and run bin/tennis. I was wondering is it possible to make it work like a regular shell command? i.e able to run it from any dir.
Anything that is globally executable, lies under one of the directories in the $PATH variable (%PATH% on Windows).
For example, $PATH may look like this:
$ echo $PATH
/usr/local/opt/rbenv/shims:/Users/casraf/bin:/Users/casraf/bin:/usr/local/heroku/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/opt/fzf/bin
You may add directories to this list, separating with :, and each of these paths will be looked into when executing a command globally.
So you could either:
Save a copy of the executable in the gem exec dir:
ln -s /your/bin/file $(ruby -rubygems -e 'puts Gem.dir')
This will create a symbolic link to your bin, inside the regular gem executable dir (it should already be in your $PATH, if not, just add it:
export PATH=$(ruby -rubygems -e 'puts Gem.dir'):$PATH
You can put this in your .bashrc or .bash_profile to make sure it happens on every terminal session (if you have a non-standard setup, you may need to find another file to put this in)
Or just add the regular path to your PATH variable:
PATH=/path/to/gem/bin:$PATH

Why might "--enable-load-relative" not work for a ruby install?

I need to install ruby at several sites, but the exact location of the install may be slightly different between the various sites.
I configured and compiled using the -enable-load-relative. This seems to work for my linux install but not for aix. When I configured for linux I used
--enable-load-relative --prefix=blah --exec-prefix=blah/linux_code_rel
I was able to test the relative loading by doing the following:
first with the install dir named linux_code_rel
blah/linux_code_rel/bin/ruby -e " puts 'hello' "
then after renaming the directory to linux_code, ran
blah/linux_code/bin/ruby -e " puts 'hello' "
both times I got back hello
When I did the same thing for aix, it does not seem to work.
I configured and installed using
--enable-load-relative --prefix=blah --exec-prefix=blah/aix_code_rel
after installing if I run
blah/aix_code_rel/bin/ruby -e "puts 'hello' "
I get back
hello
if i rename aix_code_rel to aix_code and run
blah/aix_code/bin/ruby -e "puts 'hello' "
I get
<internal:gem_prelude>:1:in `require': cannot load such file -- rubygems.rb (LoadError)
from <internal:gem_prelude>:1:in `<compiled>'
creating a symbolic link using ln -s aix_code aix_code_rel, seems to fix this, which indicates that the install is always looking for the code to be found using the path blah/aix_code_rel , despite the fact that i configured with --enable-load-relative
I seem to be able to get past this by setting the RUBYLIB env variable, but this seems messy, especially given that the linux install seems to work with the relative loading.
Anyone have an idea what I might be doing wrong? Is there any other why I can set the default LOAD_PATH? Maybe some post install configuration file?
I've not tried that option but on AIX that will be some trick to get it to work.
If you find an executable or a shared library (like miniruby or libruby.so.xxxxx) and do:
dump -H miniruby
you will see output that shows what it depends upon. Below the "Import File Strings" you will see a list. The 0th entry is what that particular executable or shared library uses for its "libpath". You could make those relative paths. It does work. But that introduces a security risk (which I just recently was told of) that the Ruby build process tries to avoid.
This is if LIBPATH is not set in the environment. If LIBPATH is set in the environment, then it will use that path in all cases.
Oh... there is actually an exception to this. (I'm editing as I'm typing) The 1st through nth entries in the import file strings list can be absolute paths in which case not even LIBPATH will alter the search since there is no search done.
What might work is to wrapper "ruby" in a script that sets LIBPATH and then exec's ruby using the same arguments. Something like:
#!/bin/sh
export LIBPATH=/blah:/ble/blah:/usr/lib:/lib
exec real-ruby "$#"
The small dance that you have to do or worry about is if ruby looks at argv[0] and does different things based upon its name. I don't think it does. And the other part is that you might need to set GEM_HOME and some of the other ruby environment variables.
The other real world suggesting is to create a symlink from where it is suppose to be installed to the place that it is installed. Do this for the bin and lib directory and that might work as well.

shebang for multiple versions

In my large collection of Ruby scripts, I do start my scripts with the common shebang:
#!/usr/bin/env ruby
Now I am finding some scripts that do need certain Ruby version, and no, they are no Rails apps that can be deployed under a specific Ruby version. They are just single file scripts that can be launched from the command line and fail to work with the system version.
Is there any way to write a shebang that sets the environment with rbenv/rvm before running the following code of the file?
You don't necessarily need to set up any environment. All you need is the path to the ruby binary you want to run and everything else will follow.
Here's an example on how you could set it up:
Create a folder ~/bin. This will hold pointers (symlinks) to all your personal ruby binaries.
Update your shell PATH so that ~/bin is included in the search path for executables.
Symlink any ruby binary you need in your ~/bin to the actual ruby binary.
For example in my ~/bin I have:
ruby18 -> /opt/ruby18/bin/ruby
ruby19 -> /opt/ruby19/bin/ruby
ruby20 -> /opt/ruby20/bin/ruby
Now let's say you have a script which needs 1.9 to run. Then all you need to do is:
#!/usr/bin/env ruby19
This will work if you have installed your gems into the default gem directory for each ruby executable. If you have installed gems somewhere else then it gets more complicated and you would need to modify GEM_PATH before you run your script.
If you don't want to get fancy with ~/bin then just hardcode your shebang line instead to point directly to the ruby binary:
#!/opt/ruby19/bin/ruby
...or the equivalent rbenv/rvm path.
Having symlinks in your ~/bin though will allow you to more easily update your bin pointers if let's say you compile a new patch of ruby 1.9, and you want to place it in another folder like /opt/ruby19-p123. Then you just need to update the symlink in ~/bin and all your scripts will run the new patched version.
rbenv will look for the .ruby-version file set by (for example)
$ rbenv local 1.9.3-p448
Create a simple file, check
#!/usr/bin/env ruby
puts RUBY_VERSION
Make it executable
$ chmod +x check
Run it
$ ./check
Output
1.9.3
That said, this is not a per-file setting. If there's a way to alter rbenv's behavior using the shebang, that would probably be a better fit.

Ruby: How to load a file into interactive ruby console (IRB)?

I am using IRB (interactive ruby console) to learn how to program with Ruby. How do I load a file into the console if I write my programs in a text editor first?
If you only need to load one file into IRB you can invoke it with irb -r ./your_file.rb if it is in the same directory.
This automatically requires the file and allows you to work with it immediately.
Using ruby 1.9.3 on Ubuntu 14.04, I am able to load files from the current directory into irb with the following command line:
irb -I . -r foo.rb
where foo.rb is the file I want to load from my current directory. The -I option is necessary to add the current directory (.) to ruby's load path, as explained in the ruby man page. This makes it possible to require files from the current directory, which is what the -r option to irb accomplishes.
The key piece that wasn't obvious for me when I had this problem is the -I option. Once you do that, you can call require 'foo.rb' from within irb for any files in the current directory. And of course, you can specify any directory you want, not just . with the -I option. To include multiple directories on the load path, separate them with a colon (:), e.g.:
irb -I foo/:bar/:baz/
This command will add the directories foo, bar, and baz to ruby's load path.
The final alternative is to use the relative or absolute path to the file when using require or -r to load a file:
irb -r ./foo.rb
or from within irb:
> require './foo.rb'
Type in irb
And then
require './ruby_file.rb'
This is assuming that ruby_file.rb is in the same directory. Adjust accordingly.
Two ways:
to load source without running the program -- this gives access to all variables and functions:
source("filename.rb")
to run program and then drop into interactive mode -- this only gives access to functions, not variables:
require("filename.rb")
It depends on your ruby. Ruby 1.8 includes your current path, while ruby 1.9 does not. Evaluate $: to determine if your path is included or not. So in ruby 1.9 you must use the entire path, which is always a safe bet.
Then you can use require or load to include the file.
require does not require you to add the suffix of the file when trying to find it and will only include the file once. require should be used instead of load most of the time.
Check out Adding a directory to $LOAD_PATH (Ruby) if you are going to be using ruby 1.8
Type the ruby codes in the text editor
Save it with the extension .rb (for example: demo.rb).
In linux, open your terminal then change directory to the current location of that file (cd command is used to change directory).
After that,type irb and your filename(don't forget to include your extension(.rb)).
In that image,I loaded a simple ruby file which only prints "ruby".
Another way to load the path into irb is just type require then drag and drop the file into the terminal.🙂
-tested using Linux Mint.
For those, who want to load .rb file from the different directory. Just add a string representer of the directory to $: variable.
> $: << "/directory/to/the/required/rb/file"
> require "file"

How to specify rubygems path in environment-less Ruby script?

I've written a data collection script for Cacti in Ruby and it runs fine from the command line but Cacti runs the script via "env -i" which strips the environment so Ruby can't find the rubygems library ("in `require': no such file to load -- rubygems (LoadError)"). How might I work around this?
#!/bin/sh
#export LOAD_PATH=whatever
#export RUBYLIB=whatever
#export RUBYOPT=whatever
#export RUBYPATH=whatever
#export RUBYSHELL=whatever
#export PATH=$PATH:whatever
exec ruby -x. $0 "$#"
#!/usr/bin/ruby
require 'rubygems'
require 'open4' # or whatever
# rest of ruby script here
This is a shell script that runs ruby with -x, which will cause the interpreter to skip lines until it finds #!.*ruby. This will give you a chance to restore the environment. The . after -x is a noop, you can take out the ., or replace it with a directory. Ruby will cd there before running the script.
I'm actually guessing that this is not really what you want, since this could have been done without any trickery by just making two scripts, one for the shell, one for Ruby. Perhaps the list of environment variables Ruby cares about will help...
I don't think $LOAD_PATH used for gems (at least, not exclusively). You might want to look at a couple environment variables that haven't been mentioned here yet:
ENV['GEM_HOME']
ENV['GEM_PATH']
You can see your current paths for gems with:
require 'rubygems'
puts Gem.path
A partial answer might be here: comp.lang.ruby post
Can you modify any of the following in your Ruby script: $:, $-I or $LOAD_PATH? These all just point to the same array which specifies where Ruby looks for classes and other ephemera...
>> $LOAD_PATH
=> ["/usr/local/lib/ruby/site_ruby/1.8", "/usr/local/lib/ruby/site_ruby/1.8/i686-darwin9.5.0", "/usr/local/lib/ruby/site_ruby", "/usr/local/lib/ruby/1.8", "/usr/local/lib/ruby/1.8/i686-darwin9.5.0", "."]

Resources