best practices for transfering ruby gems collectio

2019-06-09 05:43发布

问题:

i want to copy all of my gems from one machine (foo) to another (bar). both machines are identical except that foo has a bunch of gems installed and bar does not (bar cannot get onto the internet).

i copied /usr/local/lib/ruby/gems from foo to bar, and now bar recognizes that the gems are installed.

root@bar # gem list

*** LOCAL GEMS ***

keybox (1.2.1)
rake (0.9.2.2)
... and so on

if i try to run them from their native location, they work as expected

root@bar # cd /usr/local/lib/ruby/gems/1.8/gems/keybox-1.2.1/bin
root@bar # ./keybox --version
keybox: version 1.2.1

i would like to have all gems under a common bin dir, like they are on foo

root@bar # find /usr/local/lib/ruby/gems/1.8/gems/*/bin -type f | xargs -I baz ln -s baz /usr/local/bin/ 

as expected, this creates symbolic links from each gem's location to /usr/local/bin/

for some gems (like rake) everything works as expected, for others (like keybox) it does not work. for some gems, there's a difference between the script in the gem dir and the one that gets installed under /usr/local/bin.

root@foo # diff /usr/local/lib/ruby/gems/1.8/gems/keybox-1.2.1/bin/keybox /usr/local/bin/keybox 
1,4c1,7
< #!/usr/bin/env ruby
< ########################################################################
< # 
< ########################################################################
---
> #!/usr/local/bin/ruby18
> #
> # This file was generated by RubyGems.
> #
> # The application 'keybox' is installed as part of a gem, and
> # this file is here to facilitate running it.
> #
6,17c9
< #----------------------------------------------------------------------
< # bootstrap
< #----------------------------------------------------------------------
< begin
<     require 'keybox'
<     require 'keybox/application/password_safe'
< rescue LoadError 
<     path = File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
<     raise if $:.include? path
<     $: << path
<     retry
< end
---
> require 'rubygems'
19,21c11
< #----------------------------------------------------------------------
< # instantiate the program and pass it the commandline parameters
< #----------------------------------------------------------------------
---    
> version = ">= 0"
23,24c13,16
< keybox = Keybox::Application::PasswordSafe.new(ARGV)
< keybox.run
---
> if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
>   version = $1
>   ARGV.shift
> end
25a18,19
> gem 'keybox', version
> load Gem.bin_path('keybox', 'keybox', version)

since i'm already copying gems from one machine to another i could just as easily copy the public scripts as well, but is there a more "gemish" way to do it? is there a gem command that will regenerate the public scripts as has apparently been done in the case of keybox?

回答1:

If you installed the gems via ports, the following should work

  1. Make a list of all gems, like pkg_info | grep rubygem | cut -d ' ' -f 1
  2. Use 'pkg_create -Rnb' to create packages from locally installed ports (and necessary dependencies).
  3. Copy the packages to the target machine
  4. Install them there with pkg_add.


回答2:

Try using the following command:

gem pristine --all

That will reinstall the gems from the cached source (which I believe you copied), and therefore should recreate script wrappers, recompile extensions, etc.

You can also check the documentation to adjust the command to suit your needs (there's a flag to just restore the executables, if that's all you want to do).