Tôi đã có một deploy.rb có thể triển khai ứng dụng của tôi trên máy chủ sản xuất của tôi.
Ứng dụng của tôi chứa một tác vụ rake tùy chỉnh (tệp .rake trong thư mục lib / task).
Tôi muốn tạo một nhiệm vụ nắp sẽ chạy tác vụ cào đó từ xa.
Tôi đã có một deploy.rb có thể triển khai ứng dụng của tôi trên máy chủ sản xuất của tôi.
Ứng dụng của tôi chứa một tác vụ rake tùy chỉnh (tệp .rake trong thư mục lib / task).
Tôi muốn tạo một nhiệm vụ nắp sẽ chạy tác vụ cào đó từ xa.
Câu trả lời:
Rõ ràng hơn một chút, trong của bạn \config\deploy.rb
, thêm bên ngoài bất kỳ tác vụ hoặc không gian tên nào:
namespace :rake do
desc "Run a task on a remote server."
# run like: cap staging rake:invoke task=a_certain_task
task :invoke do
run("cd #{deploy_to}/current; /usr/bin/env rake #{ENV['task']} RAILS_ENV=#{rails_env}")
end
end
Sau đó, từ /rails_root/
, bạn có thể chạy:
cap staging rake:invoke task=rebuild_table_abc
... vài năm sau ...
Hãy xem plugin rails của capistrano, bạn có thể xem tại https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/migrations.rake#L5-L14, nó có thể trông giống như sau:
desc 'Runs rake db:migrate if migrations are set'
task :migrate => [:set_rails_env] do
on primary fetch(:migration_role) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "db:migrate"
end
end
end
end
run
sẽ hoạt động trên capistrano cho đến phiên bản 2. Từ phiên bản 3, đây là cách để đi.
Capistrano 3 Phiên bản Chung (chạy bất kỳ nhiệm vụ cào nào)
Xây dựng một phiên bản chung cho câu trả lời của Mirek Rusin:
desc 'Invoke a rake command on the remote server'
task :invoke, [:command] => 'deploy:set_rails_env' do |task, args|
on primary(:app) do
within current_path do
with :rails_env => fetch(:rails_env) do
rake args[:command]
end
end
end
end
Ví dụ sử dụng: cap staging "invoke[db:migrate]"
Lưu ý rằng deploy:set_rails_env
yêu cầu đến từ đá quý capistrano-rails
rake args[:command]
với execute :rake, "#{args.command}[#{args.extras.join(",")}]"
bạn có thể thực hiện một nhiệm vụ với nhiều luận cứ thích như vậy: cap production invoke["task","arg1","arg2"]
cap staging invoke['task[arg1\,arg2]']
. Tôi thích cách tiếp cận này hơn cách bạn đề cập vì nó phản ánh cách gọi thực tế của rake. Với phương pháp này bạn cũng có thể chuỗi nhiều nhiệm vụ, mà thường là hữu ích: cap staging invoke['task1 task2[arg1] task3[arg2\,arg3]']
. Công trình cho cào 10.2.0 hoặc mới hơn
run("cd #{deploy_to}/current && /usr/bin/env rake `<task_name>` RAILS_ENV=production")
Tìm thấy nó với Google - http://ananelson.com/said/on/2007/12/30/remote-rake-tasks-with-capistrano/
Đó RAILS_ENV=production
là một gotcha - tôi đã không nghĩ về nó lúc đầu và không thể tìm ra lý do tại sao nhiệm vụ không thực hiện được gì.
"cd #{deploy_to}/current && #{rake} <task_name> RAILS_ENV=production"
Có một cách phổ biến sẽ "chỉ hoạt động" với require 'bundler/capistrano'
và các tiện ích mở rộng khác sửa đổi rake. Điều này cũng sẽ hoạt động với môi trường tiền sản xuất nếu bạn đang sử dụng nhiều tầng. Ý chính? Sử dụng các cấu hình khác nếu bạn có thể.
desc "Run the super-awesome rake task"
task :super_awesome do
rake = fetch(:rake, 'rake')
rails_env = fetch(:rails_env, 'production')
run "cd '#{current_path}' && #{rake} super_awesome RAILS_ENV=#{rails_env}"
end
top.run
thay vì chỉrun
top
phương pháp . Trong trường hợp chúng tôi đã xác định run
trong cùng một không gian tên, top.run
là bắt buộc, nếu không nó vẫn sẽ tìm thấy cấp cao nhất run
ngay cả khi nhiệm vụ được đặt trong không gian tên. Tôi đã bỏ lỡ một cái gì đó? Điều gì đã xảy ra trong trường hợp của bạn?
capistrano-rake
đá quýChỉ cần cài đặt đá quý mà không cần phải làm phiền với các công thức capistrano tùy chỉnh và thực hiện các nhiệm vụ cào mong muốn trên các máy chủ từ xa như thế này:
cap production invoke:rake TASK=my:rake_task
Tiết lộ đầy đủ: Tôi đã viết nó
Cá nhân tôi sử dụng trong sản xuất một phương pháp trợ giúp như thế này:
def run_rake(task, options={}, &block)
command = "cd #{latest_release} && /usr/bin/env bundle exec rake #{task}"
run(command, options, &block)
end
Điều đó cho phép chạy tác vụ rake tương tự như sử dụng phương thức run (lệnh).
LƯU Ý: Nó tương tự như những gì Duke đề xuất, nhưng tôi:
Có một chiếc áo choàng đá quý thú vị giúp các nhiệm vụ cào của bạn có sẵn dưới dạng các nhiệm vụ Capistrano, vì vậy bạn có thể chạy chúng từ xa. cape
được ghi lại đầy đủ, nhưng đây là tổng quan ngắn về cách thiết lập tôi.
Sau khi cài đặt gem, chỉ cần thêm nó vào config/deploy.rb
tệp của bạn .
# config/deploy.rb
require 'cape'
Cape do
# Create Capistrano recipes for all Rake tasks.
mirror_rake_tasks
end
Giờ đây, bạn có thể chạy tất cả các rake
tác vụ của mình cục bộ hoặc từ xa thông qua cap
.
Như một phần thưởng bổ sung, cape
cho phép bạn đặt cách bạn muốn chạy tác vụ cào cục bộ và từ xa (không cần nữa bundle exec rake
), chỉ cần thêm điều này vào config/deploy.rb
tệp của bạn :
# Configure Cape to execute Rake via Bundler, both locally and remotely.
Cape.local_rake_executable = '/usr/bin/env bundle exec rake'
Cape.remote_rake_executable = '/usr/bin/env bundle exec rake'
namespace :rake_task do
task :invoke do
if ENV['COMMAND'].to_s.strip == ''
puts "USAGE: cap rake_task:invoke COMMAND='db:migrate'"
else
run "cd #{current_path} && RAILS_ENV=production rake #{ENV['COMMAND']}"
end
end
end
RAILS_ENV=production
thành RAILS_ENV=#{rails_env}
cho phép nó hoạt động trên máy chủ dàn của tôi.
Đây là những gì tôi đã đưa vào deploy.rb của mình để đơn giản hóa việc chạy các tác vụ rake. Đó là một trình bao bọc đơn giản xung quanh phương thức run () của capistrano.
def rake(cmd, options={}, &block)
command = "cd #{current_release} && /usr/bin/env bundle exec rake #{cmd} RAILS_ENV=#{rails_env}"
run(command, options, &block)
end
Sau đó, tôi chỉ chạy bất kỳ tác vụ cào nào như vậy:
rake 'app:compile:jammit'
Hầu hết đó là từ câu trả lời trên với một cải tiến nhỏ để chạy bất kỳ nhiệm vụ cào nào từ capistrano
Chạy bất kỳ nhiệm vụ cào nào từ capistrano
$ cap rake -s rake_task=$rake_task
# Capfile
task :rake do
rake = fetch(:rake, 'rake')
rails_env = fetch(:rails_env, 'production')
run "cd '#{current_path}' && #{rake} #{rake_task} RAILS_ENV=#{rails_env}"
end
Điều này cũng hoạt động:
run("cd #{release_path}/current && /usr/bin/rake <rake_task_name>", :env => {'RAILS_ENV' => rails_env})
Thông tin thêm: Capistrano Run
Nếu bạn muốn có thể chuyển nhiều đối số, hãy thử điều này (dựa trên câu trả lời của marinosbern):
task :invoke, [:command] => 'deploy:set_rails_env' do |task, args|
on primary(:app) do
within current_path do
with :rails_env => fetch(:rails_env) do
execute :rake, "#{args.command}[#{args.extras.join(",")}]"
end
end
end
end
Sau đó, bạn có thể chạy một tác vụ như sau: cap production invoke["task","arg1","arg2"]
Vì vậy, tôi đã làm việc trên này. nó nối để hoạt động tốt. Tuy nhiên, bạn cần một trình định dạng để thực sự tận dụng mã.
Nếu bạn không muốn sử dụng trình định dạng, chỉ cần đặt mức nhật ký thành chế độ gỡ lỗi. Các semas này để h
SSHKit.config.output_verbosity = Logger::DEBUG
namespace :invoke do
desc 'Run a bash task on a remote server. cap environment invoke:bash[\'ls -la\'] '
task :bash, :execute do |_task, args|
on roles(:app), in: :sequence do
SSHKit.config.format = :supersimple
execute args[:execute]
end
end
desc 'Run a rake task on a remote server. cap environment invoke:rake[\'db:migrate\'] '
task :rake, :task do |_task, args|
on primary :app do
within current_path do
with rails_env: fetch(:rails_env) do
SSHKit.config.format = :supersimple
rake args[:task]
end
end
end
end
end
Đây là trình định dạng tôi đã xây dựng để làm việc với đoạn mã trên. Nó dựa trên: textimple được tích hợp trong sshkit nhưng không phải là một cách tồi để gọi các tác vụ tùy chỉnh. Ồ, nhiều cái này không hoạt động với phiên bản mới nhất của sshkit gem. Tôi biết nó hoạt động với 1.7.1. Tôi nói điều này bởi vì nhánh chính đã thay đổi các phương thức SSHKit :: Command có sẵn.
module SSHKit
module Formatter
class SuperSimple < SSHKit::Formatter::Abstract
def write(obj)
case obj
when SSHKit::Command then write_command(obj)
when SSHKit::LogMessage then write_log_message(obj)
end
end
alias :<< :write
private
def write_command(command)
unless command.started? && SSHKit.config.output_verbosity == Logger::DEBUG
original_output << "Running #{String(command)} #{command.host.user ? "as #{command.host.user}@" : "on "}#{command.host}\n"
if SSHKit.config.output_verbosity == Logger::DEBUG
original_output << "Command: #{command.to_command}" + "\n"
end
end
unless command.stdout.empty?
command.stdout.lines.each do |line|
original_output << line
original_output << "\n" unless line[-1] == "\n"
end
end
unless command.stderr.empty?
command.stderr.lines.each do |line|
original_output << line
original_output << "\n" unless line[-1] == "\n"
end
end
end
def write_log_message(log_message)
original_output << log_message.to_s + "\n"
end
end
end
end
Các câu trả lời trước đó không giúp được tôi và tôi đã tìm thấy câu trả lời này: Từ http://kenglish.co/run-rake-tasks-on-the-server-with-capistrano-3-and-rbenv/
namespace :deploy do
# ....
# @example
# bundle exec cap uat deploy:invoke task=users:update_defaults
desc 'Invoke rake task on the server'
task :invoke do
fail 'no task provided' unless ENV['task']
on roles(:app) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, ENV['task']
end
end
end
end
end
để chạy nhiệm vụ của bạn sử dụng
bundle exec cap uat deploy:invoke task=users:update_defaults
Có thể nó sẽ hữu ích cho ai đó
#{rake}
biến riêng của capistrano ? Có vẻ như nó không phải lúc nào cũng là lựa chọn tốt nhất.