我如何从Capistrano运行一个耙子任务?
我已经有一个deploy.rb,可以在我的生产服务器上部署我的应用程序。
我的应用程序包含一个自定义的rake任务(lib / tasks目录中的一个.rake文件)。
我想创build一个远程运行该rake任务的上限任务。
在你的\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
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
是个棘手的问题 – 我一开始没有想到,也不知道为什么这个任务没有做任何事情。
几年后…
看看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通用版本 (运行任何耙子任务)
build立一个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风格的耙子调用
有一个常见的方式,只require 'bundler/capistrano'
和其他修改rake的扩展就能“正常工作”。 如果您使用多阶段,这也将适用于预生产环境。 要点? 如果可以的话,使用configurationvariables。
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
这允许运行类似于使用run(command)方法的rake任务。
注:这与杜克提出的相似,但我:
- 使用latest_release而不是current_release – 从我的经验来看,它更像是你在运行rake命令时所期望的;
- 按照Rake和Capistrano的命名约定(而不是:cmd – > task和rake – > run_rake)
- 请勿设置RAILS_ENV =#{rails_env},因为设置它的正确位置是default_run_optionsvariables。 例如default_run_options [:env] = {'RAILS_ENV'=>'production'}# – > DRY!
有一个有趣的gem海angular ,使您的耙子任务作为Capistrano任务可用,所以你可以远程运行它们。 cape
是有据可查的,但这里是如何设置我的简短的概述。
安装gem后,只需将其添加到您的config/deploy.rb
文件。
# config/deploy.rb require 'cape' Cape do # Create Capistrano recipes for all Rake tasks. mirror_rake_tasks end
现在,您可以通过本地或远程运行所有您需要的任务。
作为一个额外的好处, 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中,以简化运行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运行任何耙任务
从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跑
如果你想能够传递多个参数试试这个(基于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"]
如果Rake任务需要用户交互,它将不起作用
所以我一直在做这个。 它接缝工作良好。 但是,你需要一个formater来真正利用代码。
如果您不想使用格式化程序,只需将日志级别设置为debugging模式即可。 这些semas到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
这是我为了使用上面的代码而构build的格式化程序。 它基于:sshkit中内置的textsimple,但是调用自定义任务并不是一个好方法。 哦,这很多不适用于最新版本的sshkitgem。 我知道它适用于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
我不知道capistrano是如何工作的,但只是为了logging – 这是从Ruby中调用rake任务的语法:
Rake::Task["task:name"].invoke