How to run custom rake task via capistrano 3?

2020-07-03 07:11发布

which way, i can run rake commands via capistrano on remote server.

for example i have a lib/task/reparse.rake with some methods

desc "it's take csv file, makes some changes and fill db with this info"
task :example1 => :environment do
  require 'csv'
  rows_to_insert = []
  # some actions
  # ...
end

on local server all is fine - i just run rake reparse:example1 and it's work(fill db correctly). so question is - how can i run this command on real hosting, after deploy?

i'am using rails 4.1 + capistrano 3.

P.S. examples from site not work for me How do I run a rake task from Capistrano?

if i try cap production rake:invoke task=reparse:land it fails with:

cap aborted!
Don't know how to build task 'rake:invoke'

some fixes

namespace :somenamespace do
  task :runrake do  
    on roles(:all), in: :sequence, wait: 5 do      
      within release_path do
        execute :rake, ENV['task'], "RAILS_ENV=production"
      end 
    end
  end
end

with such way it begin to execute via

cap production somenamespace:runrake task=custom_task_file:custom_method1

5条回答
放我归山
2楼-- · 2020-07-03 07:46

So I have been working on this. it seams to work well. However you need a formater to really take advantage of the code.

If you don't want to use a formatter just set the log level to to debug mode.

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 primary :app do
      within deploy_to do
        with rails_env: fetch(:rails_env) do
          SSHKit.config.format = :supersimple
          execute args[:execute]
        end
      end
    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

This is the formatter I built to work with the code above. It is based off the :textsimple built into the sshkit but it is not a bad way to invoke custom tasks. Oh this many not works with the newest version of sshkit gem. I know it works with 1.7.1. I say this because the master branch has changed the SSHKit::Command methods that are available.

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
查看更多
戒情不戒烟
3楼-- · 2020-07-03 07:49

you need to load a custom rake task in Capistrano config:

# config/deploy.rb || config/deploy/production.rb
load 'lib/task/reparse.rake'

check for new task in console cap -T

查看更多
等我变得足够好
4楼-- · 2020-07-03 07:52

Based on the capistrano/rails gem: https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/migrations.rake

namespace :somenamespace do
  task :runrake do
    on roles(:all) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, ask :task
        end
      end 
    end
  end
end
查看更多
仙女界的扛把子
5楼-- · 2020-07-03 07:57

Try capistrano-rake

Without messing with custom capistrano tasks or going into much detail, all you need to do is simply install the gem and you can start executing rake tasks on remote servers like this:

$ cap production invoke:rake TASK=some:rake_task
查看更多
▲ chillily
6楼-- · 2020-07-03 07:58

You can create a corresponding capistrano task to run a specific rake task like that:

namespace :guests do
  desc 'Remove guest users older than 7 days'
  task :clean do
    on roles(:app) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, 'guests:delete_old_guest_users'
        end
      end
    end
  end
end
查看更多
登录 后发表回答