I need to host different Ruby applications on a single server. Applications have mutually-incompatible ruby versions and gems. Is there a way to install RVM in system-wide mode and have gemsets which are also system-wide, and not tied to a specific user and their $HOME directory? Or is there a better approach altogether for hosting different Ruby apps on the same machine?
Use mixed mode installation of RVM basically you get system installation and as every user that should have his own gemsets run:
rvm user gemsets
Because of numerous problems with RVM in system-wide mode (rvmsudo not working, directories being created in filesystem root by RVM, etc.) I've decided to go down the vendor/bundle route.
I installed ruby 1.9.3 w/ latest patches using my distro's package manager and then ran gem install bundler --no-user-install which installed bundler gem system wide.
I then ran in each app's directory bundle install --path vendor/bundle --without development test which installed required production gems in app's vendor/bundle directory. If there were any rake tasks or plain ruby files to run as part of app's setup then those were prefixed with bundle exec ... (which uses the gem environment from vendor/bundle when running the command).
In the end all apps were directly runnable without any prior environment setup or RVM magic, and each have separate gems.
Related
I have limited privileges on a shared machine I'm using, so I can't install gems the way I'm used to. For example:
$ gem install request-log-analyzer
ERROR: While executing gem ... (Gem::FilePermissionError)
You don't have write permissions into the /usr/lib/ruby/gems/1.8 directory.
Is it possible to install a gem locally? (if it matters, I'm trying to install this gem.)
I saw a number of posts on Stack Overflow that talked about using Bundler or gemfiles but I'm not installing this gem for a Ruby on Rails project - I just want to use it in isolation.
I'm running Linux, not sure which flavor though.
You can try:
gem install --user-install gem_name
Add the --local flag to your install:
gem install --local request-log-analyzer
If that causes any problems, try downloading the gem manually and pointing gem directly to it using:
gem install --local path/to/gem/filename.gem
If you want to install it to your user home, as per rubygems:
When you use the --user-install option, RubyGems will install the gems
to a directory inside your home directory, something like
~/.gem/ruby/1.9.1. The commands provided by the gems you installed
will end up in ~/.gem/ruby/1.9.1/bin. For the programs installed there
to be available for you, you need to add ~/.gem/ruby/1.9.1/bin to your
PATH environment variable.
The command for this would just be
gem install --user-install request-log-analyzer
You could just use RVM: Ruby Version Manager. It is a complete version manager, along the lines of node version manager (nvm) and others, in that it allows you to have different versions of ruby and different collections of gems for each project. It does the job of keeping gems isolated from each other as well as from the system ruby, but at the expense of learning a complete version manager.
When run without root, it installs locally in ~/.rvm and doesn't affect other users.
How do I install the gem command locally?
I'm on a shared hosting, the machine has ruby installed, but I need to get the gem command installed to $HOME/opt so I can install ruby modules like sass.
You can install rvm into the $HOME/.rvm folder, and use with it non-system rubies, and gemsets, just install required ruby, and create newly named gemset from within the rvm session. All of them will be stored in yuor home folder.
In case if you strictly with to use $HOME/opt, you shell install the rvm, then move its folder to the $HOME/opt, set properly PATH environment variable up, and fix call to rvm in the $HOME/.bash_profile.
i've read the documentation from rubygems site, but i guess the "gem install" command always reinstall, recompile everything, even if the same version already installed..
how to make gem install command only install when needed?
It looks like the --conservative flag will make the gem command do what you want.
gem install rake --conservative
From the documentation gem install --help:
--conservative Don't attempt to upgrade gems already meeting version requirement
You may want to use something external like gembundler to handle project’s gem installation.
If you must use rubygems directly for this, a command like
ruby -e "puts `gem install GEMTOINSTALL` if(`gem list --no-versions | grep GEMTOINSTALL`) == ''"
would do the job.
That is why we use bundle install. This command will look into the gemfile for the gems.
This Gemfile says a few things. First, it says that bundler should look for gems declared in the Gemfile at http://rubygems.org. You can declare multiple Rubygems sources, and bundler will look for gems in the order you declared the sources.
Bundler will connect to rubygems.org (and any other sources that you declared), and find a list of all of the required gems that meet the requirements you specified. Because all of the gems in your Gemfile have dependencies of their own (and some of those have their own dependencies), running bundle install on the Gemfile will install quite a few gems.
If any of the needed gems are already installed, Bundler will use them. After installing any needed gems to your system, bundler writes a snapshot of all of the gems and versions that it installed to Gemfile.lock.
When you run bundle install, bundler will (by default), install your gems to your system repository of gems. This means that they will show up in gem list. Additionally, if you are developing a number of applications, you will not need to download and install gems in common for each application. This is nice for development, but somewhat problematic for deployment.
In a deployment scenario, the Unix user you deploy with may not have access to install gems to a system location. Even if the user does (or you use sudo), the user that boots the application may not have access to them.
As a result, bundler comes with a --deployment flag that encapsulates the best practices for using bundler in a deployment environment.
The --deployment flag requires an up-to-date Gemfile.lock to ensure that the testing you have done (in development and staging) actually reflects the code you put into production. You can run bundle check before deploying your application to make sure that your Gemfile.lock is up-to-date. Note that it will always be up-to-date if you have run bundle install, successfully booted your application (or run your tests) since the last time you changed your Gemfile.
The following code lives inside my rails app's root folder and daemonizes/runs myserver.rb.
# myserver_control.rb
require 'rubygems'
require 'daemons' # causes 'no such file to load -- daemons' error since gem reinstall with rvm
#options = {
# options defined
}
Daemons.run('myserver.rb', #options)
It was working just fine until I installed rvm and now it can't seem to find the daemons gem. I have a feeling maybe the above is searching for the daemons gem in a system wide folder somewhere? Instead of being able to use the rvm installed daemons gem? How do I install the daemons gem on a system level where it can find it? OR how do I make it so it can find the rvm installed gem?
Currently I do not even have a 'system' gem set. How would I install gems on the system level after having already installed rvm?
If wishing to use the system ruby and gems you can type in
rvm use system
which will allow to use the system installed ruby and gems, but I think this kinda of defeats the purpose of using RVM I would instead install a default ruby in RVM and install any gems into that. To set a default Ruby after you have installed it, type this
rvm --default use 1.9.2
Edit
Based on comment your problem lies with running sudo, this creates a new subshell and different instance of rvm
RVM uses a concept of gemsets, which are unique groups of gems that you can use, most often specific to ruby versions (although you can make them specific to applications or global).
RVM will change your GEM_HOME when changing ruby versions, which tells ru ygems where your gems are installed. So when you installed RVM, you created a new blank gemset and RVM told rubygems to use that.
This is because gems are not always cross compatible between rubygems.
However, if you just writing rails apps, you should ignore the above for now and use bundler. Place 'gem "daemon"' I am your Gemfile and run bundle update from your app root directory.
Bundle helps you maintain gems on a per app basis, which means your app won't break if you upgrade a gem somewhere else. Using it and knowing how it works is best practices. Good luck.
Quick question about gem installation -- when I use bundle install I know it installs the gems necessary for my individual project, but it doesn't affect other projects on my computer. If I use gem install name_of_gem would that also only affect the current project or would it affect all projects on my computer using rails (a generic installation)? In general I think I am a little confused about how exactly gem installation works, so if your answer could include some general background information to help me understand this that would be great!
Yes, gems are typically installed system-wide, or in your home directory is this is not possible. By default, when your application uses a gem, RubyGems loads the latest installed version. If you want to use a specific version, RubyGems lets you do that with this syntax:
require 'rubygems'
gem 'RedCloth', '3.0'
Bundler is a helpful tool that tracks the versions of a gem that are being used to develop a project, and then allows you to both install them in one fell swoop with bundle install, and also to load those exact versions. The application loads them by loading the Bundler code, which overrides parts of RubyGems to use the versions specified in the Gemfile.
By default, Bundler just calls RubyGems to install gems (again, system-wide or in your homedir). You can ask it to store the gems in a directory called vendor/cache by using bundle package. This lets you "freeze" the gems so that you can distribute them with the source code.
If you want further isolation of your Ruby environments, you should use RVM, which lets you set up isolated gemsets, and in fact, different versions of Ruby, to use on different projects. When you're using RVM, the directory where RubyGems installs things is overridden and is specific to your current Ruby version and gemset.
I'd recommend reading the docs for both RubyGems and Bundler; they're both quite good.
When you do bundle install the gems are installed at rubygems and would be available for all your projects unless you're using RVM and setting up gemsets for your projects.
When you're not using RVM and you do a gem install your operating system is probably going to install the gem at your current user's files (usually ~/.gem), if you sudo install gem it's going to install wherever is the place your system Ruby is installed.
I would really recommend you to setup RVM do manage separate groups of gems and rubies. You can read their website linked above or a simple tutorial I wrote to use it.