使用不同版本 Ruby 的 UNIX `system` 命令

UNIX `system` command using different version of Ruby

我有一个包含以下内容的 Rakefile:

namespace :geo_data do
  desc 'Imports geo data to Heroku'
  task :heroku_import => :environment do
    system "heroku pg:psql DATABASE -c 'DELETE FROM <table name>' -a <heroku app name>"

    # some more stuff...
  end
end

每当我 运行 rake geo_data:heroku_import 时,它都会在我的 Heroku 命令上崩溃并出现以下错误:

Your Ruby version is 1.9.3, but your Gemfile specified 2.2.2

但是,如果我 运行 Heroku 命令 - heroku pg:psql DATABASE -c 'DELETE FROM <table name>' -a <heroku app name> - 直接从终端的命令行 window,它工作正常。

因此 system 命令似乎使用了不同版本的 Ruby。

有趣的是,据我所知,我的机器上什至没有安装 1.9.3。这是 rvm list:

的输出
rvm rubies

   ruby-2.0.0-p598 [ x86_64 ]
   ruby-2.2.0 [ x86_64 ]
=* ruby-2.2.2 [ x86_64 ]

# => - current
# =* - current && default
#  * - default

根据该输出,我没有安装 1.9.32.2.2 被设置为我当前的 默认 Ruby 版本.

我确定 system 使用的是不同版本的 Ruby 是否正确,还是我遗漏了什么?如果它使用不同的版本,我怎样才能让它使用 2.2.2 (或者最好是 无论我的默认设置是什么 )?


更新

这是我的 Gemfile 的内容:

source 'https://rubygems.org'

ruby '2.2.2'

gem 'rails', '4.2.3'
gem 'rails-api'
gem 'spring', :group => :development
gem 'pg'
gem 'stripe'
gem 'jsonapi-resources', '0.7.0'
gem 'rails_api_auth'
gem 'rack-cors', require: 'rack/cors'
gem 'activerecord-postgis-adapter'
gem 'rgeo-geojson'
gem 'geocoder'
gem 'activerecord-import'
gem 'sidekiq'
gem 'unicorn'

group :development, :test do
  gem 'rspec-rails'
  gem 'forgery'
  gem 'foreman'
end

group :development do
  gem 'pry-rails'
end

尝试:

bundle exec rake <command>

这会在当前包的上下文中运行 rake 命令。

可在此处获取更多信息:

What does bundle exec rake mean?

看这里How to fix "Your Ruby version is 1.9.3, but your Gemfile specified 2.0.0"

尝试ruby -v

我已经通过 运行 rvm install 2.2.2.

解决了这个问题

启动时 Ruby 会检查一些环境变量,您可以使用它们来控制加载路径和设置选项等内容。

Bundler 具有“传染性”,因为当您使用它时,它会添加其中一些环境变量,以便作为子进程执行的另一个 Ruby 进程将自动尝试使用具有相同 Gemfile.

在使用 Bundler 的项目中比较 ruby -e "puts ENV.inspect"bundle exec ruby -e "puts ENV.inspect" 的输出。

这通常是您希望发生的情况,因此您始终使用 Gemfile.

中定义的 Gems 和 Ruby 版本

heroku 命令包括它自己安装的 Ruby(它在我机器上的 /usr/local/heroku/ruby 中),它使用而不是你的普通版本。这是相当旧的 Ruby 版本,我的是 1.9.3p194。

因此,当您使用 system 到 运行 heroku 命令时,创建的 Ruby 进程会检查环境变量并加载 Bundler(使用 Gem 来自您正在使用的 Ruby 版本),然后尝试根据您的 Gemfile 设置所有内容。这是 Ruby 版本不匹配的地方。

要解决此问题,您需要告诉 Bundler 在启动子进程时不要包含各种环境变量。有几种方法可以解决这个问题,在你的情况下你想使用 Bundler.clean_system 而不是普通的 system:

Bundler.clean_system "heroku pg:psql DATABASE -c 'DELETE FROM <table name>' -a <heroku app name>"

这将允许 Heroku 客户端 运行 不受 Bundler 和您的 Gemfile 的干扰。