Вопрос

У меня уже есть файл Deploy.rb, с помощью которого можно развернуть мое приложение на рабочем сервере.

Мое приложение содержит специальную задачу rake (файл .rake в каталоге lib/tasks).

Я хотел бы создать задачу ограничения, которая будет удаленно запускать эту задачу рейка.

Это было полезно?

Решение 2

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 был хитом - сначала я не думал об этом и не мог понять, почему задача ничего не делала.

Другие советы

Чуть более явно, в вашем \ 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

... пару лет спустя ...

Взгляните на плагин Capistrano's 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

Универсальная версия Capistrano 3 (запустите любую рейк-задачу)

Создание общей версии ответа Мирека Русина:

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

Использовать грабли в стиле 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

Используйте capistrano-rake gem

Просто установите драгоценный камень, не вмешиваясь в пользовательские рецепты capistrano, и выполняйте требуемые грабли на удаленных серверах следующим образом:

cap production invoke:rake TASK=my:rake_task

Полное раскрытие: я написал это

Лично я использую в производстве такой вспомогательный метод:

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).


ПРИМЕЧАНИЕ:Это похоже на то, что герцог предложил, но я:

  • используйтеlatest_release вместо current_release — по моему опыту, это больше того, что вы ожидаете при запуске команды rake;
  • следуйте соглашению об именах Rake и Capistrano (вместо:cmd -> задача и грабли -> run_rake)
  • не устанавливайте RAILS_ENV=#{rails_env}, потому что правильным местом для его установки является переменная default_run_options.Например, default_run_options[:env] = {'RAILS_ENV' => 'production'} # -> DRY!

Существует интересная вещь cape , которая делает ваши рейковые задачи доступными как задачи Capistrano, так что вы можете их запускать удаленно. cape хорошо документирован, но вот краткий обзор того, как его настроить.

После установки гема просто добавьте его в свой файл config / deploy.rb .

# config/deploy.rb
require 'cape'
Cape do
  # Create Capistrano recipes for all Rake tasks.
  mirror_rake_tasks
end

Теперь вы можете выполнять все свои задачи rake локально или удаленно с помощью cap .

В качестве дополнительного бонуса cape позволяет вам указать, как вы хотите запускать задачу rake локально и удаленно (не более 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'
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 

Вот что я поместил в своем deploy.rb, чтобы упростить запуск граблей. Это простая оболочка для метода run () 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

Тогда я просто запускаю любую задачу с граблями, вот так:

rake 'app:compile:jammit'

Это сработало для меня:

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] "

Большинство из них из вышеупомянутого ответа с небольшим улучшением для запуска любой грабли из капистрано

Запустите любую задачу с граблями из Капистрано

$ 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

Это также работает:

run("cd #{release_path}/current && /usr/bin/rake <rake_task_name>", :env => {'RAILS_ENV' => rails_env})

Дополнительная информация: Запуск Capistrano

Если вы хотите передать несколько аргументов, попробуйте это (основываясь на ответе Мариносберна):

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 "]

Так что я работал над этим. это швы, чтобы работать хорошо. Однако вам нужен форматер, чтобы действительно воспользоваться преимуществами кода.

Если вы не хотите использовать средство форматирования, просто установите уровень журнала в режим отладки. Эти семы на ч

SSHKit.config.output_verbosity = Logger::DEBUG

Cap Capff

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

Это форматтер, который я создал для работы с кодом выше. Он основан на: текстовом простом встроенном в sshkit, но это не плохой способ вызывать пользовательские задачи. Ох уж это не работает с новейшей версией сшкит гема. Я знаю, что это работает с 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top