我已经有一个部署。rb,可以部署我在生产服务器。

我的应用程序包含一个定制的瑞克的任务(a。瑞克文件在lib/任务目录)。

我想创建一个盖的任务是将远程运行,瑞克的任务。

有帮助吗?

解决方案 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的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 Generic Version (运行任何佣金任务)

构建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

用法示例:cap staging "invoke[db:migrate]"

请注意,deploy:set_rails_env需要来自capistrano-rails gem

使用Capistrano风格的rake调用

有一种常见的方式''<!>“只是工作<!>”;使用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

只需安装gem而不会弄乱自定义capistrano配方,并在远程服务器上执行所需的rake任务,如下所示:

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

允许运行耙任务类似于使用的运行(命令)的方法。


注:它是相似的什么 公爵 提议,但我:

  • 使用latest_release而不是current_release-从我的经验这是什么,你指望当运行一耙命令;
  • 遵循命名《公约》的瑞克和卡皮斯特拉诺(而不是:cmd->的任务和耙->run_rake)
  • 不要设置RAILS_ENV=#{rails_env}因为正确的地方设置,它是default_run_options变量。E.g default_run_options[:env]={'RAILS_ENV'=>"生产"}#->干!

有一个有趣的宝石 cape ,可以让您的佣金任务作为Capistrano任务使用,因此您可以运行它们远程。 cape有详细记录,但这里有一个简短的概述如何设置我。

安装gem后,只需将其添加到config/deploy.rb文件中。

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

现在,您可以通过rake在本地或远程运行所有cap任务。

作为额外的奖励,bundle exec rake允许您设置本地和远程运行rake任务的方式(不再需要<=>),只需将其添加到<=>文件中:

# 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中放置的简化运行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'

这对我有用:

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

大部分来自以上回答有一个小的增强功能,可以从capistrano运行任何rake任务

从capistrano

运行任何rake任务
$ 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 Run

如果你想传递多个参数,试试这个(根据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"]

所以我一直在努力。接缝运作良好。但是,您需要一个形成器才能真正利用代码。

如果您不想使用格式化程序,只需将日志级别设置为调试模式。这些semas到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

这是我为使用上面的代码而构建的格式化程序。它基于:在sshkit中内置的textsimple,但它不是一种调用自定义任务的坏方法。哦,这很多不适用于最新版本的sshkit gem。我知道它适用于1.7.1。我这样说是因为master分支已经改变了可用的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