我在使用 Capistrano 将 Ever gem 部署到我的生产环境中时遇到问题。
问题源于一个bundle exec whenever
命令,该命令触发了一些"缺少的 gem"问题(但从 shell 运行捆绑安装表明实际上一切都在那里!
我的感觉是正在发生以下两种情况之一:Bundler 在调用之前没有完全加载bundle exec
,或者以某种方式存在在错误位置运行它的路径问题。
怎么回事:
* executing `deploy'
* executing `deploy:update'
** transaction: start
* executing `deploy:update_code'
executing locally: "git ls-remote git@my-source-repository:mysource.git HEAD"
command finished in 1847ms
* executing "git clone -q git@my-source-repository:mysource.git /domains/myapp/releases/20130124211036 && cd /domains/myapp/releases/20130124211036 && git checkout -q -b deploy 90238bbcb993e3e7df2374ffaa13e7ed701c202e && (echo 90238bbcb993e3e7df2374ffaa13e7ed701c202e > /domains/myapp/releases/20130124211036/REVISION)"
servers: ["myip"]
[myip] executing command
** [myip :: out] Enter passphrase for key '/home/deploy/.ssh/id_rsa':
** [myip :: out]
command finished in 9294ms
* executing `deploy:finalize_update'
triggering before callbacks for `deploy:finalize_update'
* executing `whenever:update_crontab'
* executing "cd /domains/myapp/releases/20130124211036 && bundle exec whenever --update-crontab My App --set environment=production --roles db"
servers: ["myip"]
[myip] executing command
** [out :: myip] Could not find carrierwave-0.5.8 in any of the sources
** [out :: myip] Run `bundle install` to install missing gems.
command finished in 1967ms
*** [deploy:update_code] rolling back
* executing "rm -rf /domains/myapp/releases/20130124211036; true"
servers: ["myip"]
[myip] executing command
command finished in 998ms
failed: "rvm_path=/usr/local/rvm /usr/local/rvm/bin/rvm-shell '1.9.3' -c 'cd /domains/myapp/releases/20130124211036 && bundle exec whenever --update-crontab My App --set environment=production --roles db'" on myip
您可以看到失败来自以下行:
bundle exec whenever --update-crontab
这反过来又由我的Capistrano deploy.rb运行。
# Your Application's "Name"
set :application, [My App]
# The URL to your application's repository
set :repository, [repo]
set :scm, :git
set :scm_passphrase, [password]
# The user you are using to deploy with (This user should have SSH access to your server)
set :user, "deploy"
# We want to deploy everything under your user, and we don't want to use sudo
set :use_sudo, false
# Where to deploy your application to.
set :deploy_to, "/domains/myapp/"
# Load RVM's capistrano plugin.
require "rvm/capistrano"
set :rvm_ruby_string, '1.9.3'
set :rvm_type, :system # use system-wide RVM
# Require that we use bundler to install necessary gem dependencies
require "bundler/capistrano"
set :whenever_command, "bundle exec whenever"
require "whenever/capistrano"
# -------------------------------- Server Definitions --------------------------------
# Define the hostname of your server. If you have multiple servers for multiple purposes, we can define those below as well.
set :server_name, [server]
# We're assuming you're using a single server for your site, but if you have a seperate asset server or database server, you can specify that here.
role :app, server_name
role :web, server_name
role :db, server_name, :primary => true
# -------------------------------- Final Config --------------------------------
# This configuration option is helpful when using svn+ssh but doesn't hurt anything to leave it enabled always.
default_run_options[:pty] = true
namespace :deploy do
desc "Tell Passenger to restart the app."
task :restart do
run "touch #{deploy_to}current/tmp/restart.txt"
end
task :start do
run "cd #{deploy_to} && ln -s current/public public_html"
run "touch #{deploy_to}current/tmp/restart.txt"
end
task :symlink do
run "cd #{deploy_to} && rm current ; ln -s releases/#{release_name} current"
end
task :stop do
run "rm #{deploy_to}public_html"
end
namespace :web do
task :disable do
run "cd #{deploy_to} && rm public_html && ln -s static_site public_html"
end
task :enable do
run "cd #{deploy_to} && rm public_html && ln -s current/public public_html"
end
end
desc "Symlink shared configs and folders on each release."
task :symlink_shared do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
run "ln -nfs #{shared_path}/assets #{release_path}/public/assets"
# create symlink to uploads folder for Carrierwave resources (i.e., book cover images)
run "ln -nfs #{shared_path}/uploads #{release_path}/public/uploads"
end
desc "Sync the public/assets directory."
task :assets do
system "rsync -vr --exclude='.DS_Store' public/assets #{user}@#{application}:#{shared_path}/"
end
end
after "deploy", "deploy:migrate"
after 'deploy:update_code', 'deploy:symlink_shared'
after(:setup) do
run "rm -rf #{deploy_to}public_html"
run "mkdir #{deploy_to}static_site"
end
现在,我得到的关于CarrierWave的错误是假的 - 我已经使用CarrierWave很长时间了 - 这个问题显然源于(正如您从触发错误的命令中看到的那样)来自When本身或Bundler。
而且我认为它实际上可能与与RVM相关的路径有关。无论如何,bundle exec whenever
不起作用。
有什么想法吗?
事实证明,有几个问题,都需要解决:
- 每当 ~> 0.8 引入了 Capistrano 角色的错误时
- 每当 cap 任务在 bundle:install 之前触发(这在上面的代码中得到了确认)
请参阅此处的问题:https://github.com/javan/whenever/issues/275 和此处:https://github.com/javan/whenever/issues/269
要解决此问题,您很可能需要
- 更新服务器上的捆绑程序 (-v 1.2.3)
- 在本地更新捆绑程序
- 随时更新到最新的 (-v 0.8.2)
@ideaoforder的回答也帮助了我,以前尽管我遇到了同样的麻烦,因为require 'whenever/capistrano'
处于config/deploy.rb
的顶部,然后是require 'bundler/capistrano'
。交换这两个人有所帮助。
通常,我require 'bundler/capistrano'
始终在部署脚本的顶部。