关于cloud_foundry自己的ruby, gem, bundle

很早就大致了解cloud_foundry有自己的ruby,而不是使用系统提供的ruby。并且还有两个版本的ruby,今天终于遇到了,大致搞清楚了。

他们在哪里

首先我们要知道cloud_foundry把自己的ruby,gem装到哪里去了,这个可以去看config目录下面的deployment_info.conf文件。里面包含了一个ruby_bin_dir变量。这个路径就是ruby所在,在本机上面是:/root/cloudfoundry/.deployments/devbox/deploy/rubies/ruby-1.9.2-p180/bin。

ruby下面有什么

在bin目录下面可以看到许多已近安装的软件,包括gem、rails、rack、bundle等。
关于cloud_foundry自己的ruby, gem, bundle
这里的软件才是cf真正使用到的。
有个办法可以验证,我们在终端中直接输入:gem list --local查看安装的gem包,会发现gem非常少,bundle之类的根本没有。如果使用这个gem,那么vcap::common之类的模块也无法使用。
而如果跑到这个路径下面执行这里的gem,那么就可以看到所需要的结果了。

cf是怎么使用这里的软件的

既然知道了cf确实是使用这个位置下面的ruby的,那么到底在哪里做了这个相应的操作呢?
我们来看vcap_dev文件,在dev_setup/bin目录里面的。我在http://www.linuxidc.com/Linux/2012-08/67667.htm里面分析过,我们start的时候是通过
  1. exec_cmd("#{ruby_binary} #{vcap_launch} #{command} #{vcap_components["components"].join(" ")} -c #{deployment_config_path} -v #{vcap_path} -l #{deployment_info["deployment_log_path"]}")  
这句话来执行start的,那么这里的ruby_binary其实就是我们上面提到的ruby的绝对路径。有兴趣可以去看下代码。归根到底,这个ruby的路径还是从前面提到的deployment_info.conf文件中取得的。而这个文件其实是vcap_dev_setup在安装的时候写入的。

cf的gem和bundle如何发生作用的

我们知道要让ruby项目取得依赖,我们可以利用gem和bundle来实现。使用bundle install来安装相应的gem包,然后在项目当中写下:
  1. require "rubygems"  
  2. require "bundler/setup"  
两行代码(可以看bundler官网:http://gembundler.com/

第一步

在cf当中,第一步bundle install是在安装时完成的,现在采用chef了,就是在chef的cookbook中定义的。我在http://www.linuxidc.com/Linux/2012-08/67667.htm中已经有提到了,可以参看最后一部分,cloud controller的recipe分析,其中的cf_bundle_install就是在做bundle install。当然,这个bundle也是使用了cf自己的bunlder:File.join(node[:ruby][:path], "bin", "bundle")

第二步

然后就是两个require了,这里有两个实现方式。
首先是最简单的,看dea/lib/dea/dea.rb最开头,就有两句:
  1. require 'rubygems'  
  2. require 'bundler/setup'  
第二种要看vcap/cloud_controller/config/boot.rb文件了,这个文件的最前面有:
  1. require 'rubygems'  
  2. require 'erb'  
  3. begin  
  4.   require 'fiber'  
  5. rescue LoadError  
  6.   $stderr.puts "CloudController requires a Ruby implementation that supports Fibers"  
  7.   exit 1  
  8. end  
  9.   
  10. # Set up gems listed in the Gemfile.   
  11. gemfile = File.expand_path('../../Gemfile', __FILE__)  
  12. begin  
  13.   ENV['BUNDLE_GEMFILE'] = gemfile  
  14.   require 'bundler'  
  15.   Bundler.setup  
  16. rescue Bundler::GemNotFound => e  
  17.   STDERR.puts e.message  
  18.   STDERR.puts "Try running `bundle install`."  
  19.   exit!  
  20. end if File.exist?(gemfile)  
想必应该可以看懂了,就是在把bundle和gem加载进来。这个boot.rb被health manager调用到了,我们可以看health_manager.rb文件最前面的部分:
  1. def self.setup  
  2.   $:.unshift(lib_dir.to_s) unless $:.include?(lib_dir.to_s)  
  3.   require root.join('config''boot')  
  4.   require 'active_record'  
  5.   require 'active_support/core_ext'  
  6.   require 'yajl'  
  7.   require 'eventmachine'  
  8.   require 'nats/client'  
  9.   require 'vcap/common'  
  10.   require 'vcap/component'  
  11.   require 'vcap/logging'  
  12.   require 'vcap/rolling_metric'  
  13.   require 'vcap/priority_queue'  
也是一目了然,把上面提到的boot.rb require进去了。

相关推荐