Как выполнить задачу рейка из Capistrano?
У меня уже есть deploy.rb, который может развернуть мое приложение на моем рабочем сервере.
Мое приложение содержит настраиваемую задачу rake (файл .rake в каталоге lib/tasks).
Я бы хотел создать задачу cap, которая будет удаленно запускать эту команду rake.
Ответы
Ответ 1
run("cd #{deploy_to}/current && /usr/bin/env rake `<task_name>` RAILS_ENV=production")
Нашел его с Google - http://ananelson.com/said/on/2007/12/30/remote-rake-tasks-with-capistrano/
RAILS_ENV=production
был gotcha - я не думал об этом сначала и не мог понять, почему задача ничего не делала.
Ответ 2
Немного более явный, в вашем \config\deploy.rb
, добавить вне любой задачи или пространства имен:
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
Затем из /rails_root/
вы можете запустить:
cap staging rake:invoke task=rebuild_table_abc
Ответ 3
... пару лет спустя...
Посмотрите на плагин capistrano rails, вы можете видеть на https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/migrations.rake#L5-L14 он может выглядеть примерно так:
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
Ответ 4
Capistrano 3 Generic Version (выполнить любую команду rake)
Построение общей версии ответа Мирека Русина:
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
Пример использования: cap staging "invoke[db:migrate]"
Обратите внимание, что deploy:set_rails_env
требуется, исходя из графа capistrano-rails
Ответ 5
Используйте призывы рейки в стиле Capistrano
Существует общий способ "просто работать" с require 'bundler/capistrano'
и другими расширениями, которые изменяют rake. Это также будет работать с средами предварительной обработки, если вы используете многоступенчатый режим. Суть? Используйте config vars, если вы можете.
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
Ответ 6
Просто установите драгоценный камень, не испортивсь с помощью специальных рецептов capistrano и выполните требуемые задачи рейка на удаленных серверах, например:
cap production invoke:rake TASK=my:rake_task
Полное раскрытие: я написал его
Ответ 7
Я лично использую в производстве вспомогательный метод, подобный этому:
def run_rake(task, options={}, &block)
command = "cd #{latest_release} && /usr/bin/env bundle exec rake #{task}"
run(command, options, &block)
end
Это позволяет запускать задачу rake, аналогичную использованию метода run (command).
ПРИМЕЧАНИЕ. Это похоже на то, что предлагал герцог, но я:
- используйте last_release вместо current_release - из моего опыта это больше того, чего вы ожидаете при запуске команды rake;
- следуйте соглашению об именах Rake и Capistrano (вместо: cmd → task and rake → run_rake)
- не устанавливайте RAILS_ENV = # {rails_env}, потому что правильным местом для его установки является переменная default_run_options. Например, default_run_options [: env] = {'RAILS_ENV' = > 'production'} # → DRY!
Ответ 8
Там интересный камень cape, который делает ваши задачи рейка доступными как задачи Capistrano, поэтому вы можете запускать их удаленно. cape
хорошо документирован, но вот краткий обзор того, как настроить i.
После установки драгоценного камня просто добавьте это в свой config/deploy.rb
файл.
# config/deploy.rb
require 'cape'
Cape do
# Create Capistrano recipes for all Rake tasks.
mirror_rake_tasks
end
Теперь вы можете запускать все задачи rake
локально или удаленно через cap
.
В качестве дополнительного бонуса cape
позволяет установить, как вы хотите запускать свою рейк-задачу локально и удаленно (не более bundle exec rake
), просто добавьте это в свой файл config/deploy.rb
:
# 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'
Ответ 9
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
Ответ 10
Вот что я добавил в свой deploy.rb, чтобы упростить выполнение задач rake. Это простая оболочка вокруг метода capistrano run().
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
Затем я просто запускаю любую команду rake следующим образом:
rake 'app:compile:jammit'
Ответ 11
Это сработало для меня:
task :invoke, :command do |task, args|
on roles(:app) do
within current_path do
with rails_env: fetch(:rails_env) do
execute :rake, args[:command]
end
end
end
end
Затем просто запустите cap production "invoke[task_name]"
Ответ 12
Это также работает:
run("cd #{release_path}/current && /usr/bin/rake <rake_task_name>", :env => {'RAILS_ENV' => rails_env})
Дополнительная информация: Capistrano Run
Ответ 13
Большая часть из выше ответа с незначительным улучшением для запуска любой команды rake из capistrano
Запустите любую команду rake из 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
Ответ 14
Если вы хотите передать несколько аргументов, попробуйте это (на основе ответа 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
Затем вы можете запустить задачу следующим образом: cap production invoke["task","arg1","arg2"]
Ответ 15
Если задача Rake требует взаимодействия с пользователем, она не будет работать
Ответ 16
Итак, я работал над этим. он швы хорошо работает. Однако вам нужен форматир, чтобы действительно воспользоваться кодом.
Если вы не хотите использовать форматтера, просто установите уровень журнала в режим отладки. Эти семабы к h
SSHKit.config.output_verbosity = Logger::DEBUG
Cap Stuff
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
Это форматтер, который я построил для работы с указанным выше кодом. Он основан на: textimple встроенном в sshkit, но это не плохой способ вызвать пользовательские задачи. О, это многие не работают с новейшей версией sshkit gem. Я знаю, что это работает с 1.7.1. Я говорю это, потому что главная ветвь изменила доступные методы SSHKit:: Command.
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
Ответ 17
Я понятия не имею, как работает capistrano, но только для записи - это синтаксис, чтобы вызвать команду rake из Ruby:
Rake::Task["task:name"].invoke