Capistrano'dan bir komisyon görevini nasıl çalıştırırım?


105

Uygulamamı üretim sunucumda dağıtabilecek bir deploy.rb zaten var.

Uygulamam özel bir komisyon görevi içeriyor (lib / tasks dizininde bir .rake dosyası).

Bu tırmık görevini uzaktan çalıştıracak bir başlık görevi oluşturmak istiyorum.


2
Birisi kapistranonun kendi #{rake}değişkenini kullanmanın artılarını / eksilerini açıklayabilir mi? Görünüşe göre her zaman en iyi seçenek değil.
lulalala

Yanıtlar:


59

Biraz daha açık, sizin içinde \config\deploy.rbherhangi bir görev veya ad alanının dışına ekleyin:

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

Ardından, şuradan /rails_root/çalıştırabilirsiniz:

cap staging rake:invoke task=rebuild_table_abc

1
/ usr / bin / env rake kullanmak daha iyidir, böylece rvm kurulumları doğru tırmığı alır.
DGM

8
Varsa 'paket
yürütme

44

... birkaç yıl sonra ...

Capistrano's rails eklentisine bir göz atın, https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/migrations.rake#L5-L14 adresinde görebilirsiniz, aşağıdaki gibi görünebilir:

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

3
Bu sadece capistrano v3 içindir.
phillbaker

Çok yardımcı oldu. Teşekkürler! @Mirek Rusin
Nishant Shrivastava

diğer yanıtlar, bu kullanımın runcapistrano üzerinde sürüm 2'den sürüm 3'e kadar çalışacağı yol budur.
Don Giulio

44

Capistrano 3 Genel Sürüm (herhangi bir komisyon görevini çalıştırın)

Mirek Rusin'in cevabının genel bir versiyonunu oluşturmak:

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

Örnek kullanım: cap staging "invoke[db:migrate]"

deploy:set_rails_envGerekli olanın kapistrano-raylar gemisinden geldiğini unutmayın


1
Bu yalnızca tek bir bağımsız değişkeni destekler, eğer değiştirirseniz rake args[:command] , execute :rake, "#{args.command}[#{args.extras.join(",")}]" aşağıdaki gibi birden çok bağımsız değişken içeren bir görevi yürütebilirsiniz: cap production invoke["task","arg1","arg2"]
Robin Clowers

1
@ Robin Clowers Birden fazla argüman iletebilirsiniz, örn cap staging invoke['task[arg1\,arg2]']. Bu yaklaşımı, bahsettiğiniz yaklaşıma tercih ederim çünkü gerçek tırmık çağrışımını yansıtır. Bu yaklaşımla da sıklıkla yararlıdır birden fazla görev, zincir olabilir: cap staging invoke['task1 task2[arg1] task3[arg2\,arg3]']. 10.2.0 veya daha yenisi için çalışır
marinosb

bu harika - şunu belirtmek isterim, sunucu rollerinizden biri olarak uygulamayı eklemeniz gerekir.
lfender6445

Görünüşe göre bunun "invoke [db: migrate]" olması gerekiyordu ... Düzeltme yapıldı.
Abram

@Abram, önerdiğiniz komutla "Görevi nasıl oluşturacağımı bilmiyorum 'çağırın"
dc10

41
run("cd #{deploy_to}/current && /usr/bin/env rake `<task_name>` RAILS_ENV=production")

Google ile buldum - http://ananelson.com/said/on/2007/12/30/remote-rake-tasks-with-capistrano/

Bu RAILS_ENV=productionbir aldatmacaydı - ilk başta bunu düşünmedim ve görevin neden hiçbir şey yapmadığını anlayamadım.


2
Küçük bir gelişme: noktalı virgülü && ile değiştirirseniz, ilk ifade (dizini değiştirme) başarısız olursa ikinci ifade (komisyon görevini çalıştırma) çalışmayacaktır.
Teflon Ted

2
Birden çok sunucuya dağıtım yapıyorsanız bu işe yaramaz. Tırmık görevini birçok kez çalıştıracaktır.
Mark Redding

4
kişi "cd #{deploy_to}/current && #{rake} <task_name> RAILS_ENV=production"
kapistranonun

@Mark Redding: Rake görevleri için sunuculardan birini kendi rolüne koyabilir ve capistrano görevinizi yalnızca bu role sahip sunucularda çalışacak şekilde kısıtlayabilir misiniz?
mj1531

Deploy.rb dosyamda bir görev oluşturduğum yerde bir şey yaptım. Bu görevin üzerinde bir: roles =>: db var, öyle ki sadece db: migrate için birincil olarak tanımladığım aynı sunucuda yürütülecek.
Mark Redding

20

Capistrano tarzı tırmık çağrılarını kullanın

require 'bundler/capistrano'Tırmığı değiştiren diğer uzantılarla "yalnızca çalışmanın" yaygın bir yolu vardır . Bu, çok aşamalı kullanıyorsanız, üretim öncesi ortamlarda da çalışacaktır. Ana fikir mi? Yapabiliyorsanız yapılandırma değişkenlerini kullanın.

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

2
Bu en güzel çözüm, mümkün olduğunda capistrano değerlerini kullanır
loopj

2
Muhtemelen eklemeye değer, eğer göreviniz isim top.runrun
alanlıysa

Teşekkürler @dolzenko. Sadece yöntemin belgelerinitop buldum . runAynı isim alanında tanımladığımız durumda top.rungereklidir, aksi takdirde rungörev isim alanlı olsa bile en üst seviyeyi bulmalıdır . Bir şey mi kaçırdım? Senin durumunda ne oldu?
kaptanpete

1
Açıkça aynı ad alanında tanımlanmış herhangi bir çalıştırma yöntemim yoktu, bu yüzden buna neden ihtiyacım olduğundan emin değilim. Her durumda, Capistrano 2.0 bir geçmiş ve sonraki sürüm Rake tabanlı (işleri daha tahmin edilebilir hale getiriyor)
dolzenko

16

capistrano-rakeMücevheri kullan

Özel kapistrano tarifleriyle uğraşmadan mücevheri kurun ve aşağıdaki gibi uzak sunucularda istenen komisyon görevlerini yapın:

cap production invoke:rake TASK=my:rake_task

Tam Açıklama: Ben yazdım


7

Ben şahsen üretimde bunun gibi yardımcı bir yöntem kullanıyorum:

def run_rake(task, options={}, &block)
  command = "cd #{latest_release} && /usr/bin/env bundle exec rake #{task}"
  run(command, options, &block)
end

Bu, rake görevini çalıştır (command) yöntemini kullanmaya benzer şekilde çalıştırmaya izin verir.


NOT: Duke'un önerdiğine benzer , ancak ben:

  • current_release yerine latest_release kullanın - deneyimlerime göre bir rake komutunu çalıştırırken beklediğinizden daha fazlasıdır;
  • Rake ve Capistrano adlandırma kuralını izleyin (bunun yerine: cmd -> görev ve rake -> run_rake)
  • RAILS_ENV = # {rails_env} ayarlamayın çünkü onu ayarlamak için doğru yer default_run_options değişkendir. Örneğin default_run_options [: env] = {'RAILS_ENV' => 'üretim'} # -> KURU!

5

Tırmık görevlerinizi Capistrano görevleri olarak kullanıma sunan ilginç bir mücevher pelerini var, böylece onları uzaktan çalıştırabilirsiniz. capeiyi belgelenmiştir, ancak işte i'nin nasıl kurulacağına dair kısa bir genel bakış.

Gem'i kurduktan sonra, bunu config/deploy.rbdosyanıza eklemeniz yeterlidir.

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

Artık tüm rakegörevlerinizi yerel olarak veya uzaktan çalıştırabilirsiniz cap.

Ek bir bonus olarak, capekomisyon görevinizi yerel olarak ve uzaktan (daha fazla değil bundle exec rake) nasıl çalıştırmak istediğinizi belirlemenize olanak tanır, bunu config/deploy.rbdosyanıza eklemeniz yeterlidir:

# 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'

Not: yalnızca Capistrano v2.x için çalışır. Capistrano v3 ile uyumlu değildir.
nayiaw

3
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 

1
İyi. Onu değiştirme RAILS_ENV=productioniçin RAILS_ENV=#{rails_env}de benim basamak sunucusunda çalışmaları için izin verir.
evanrmurphy

2

Tırmık görevlerini çalıştırmayı basitleştirmek için deploy.rb dosyama koyduğum şeyler. Bu, capistrano'nun run () yöntemini temel alan basit bir sarmalayıcıdır.

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

Sonra herhangi bir komisyon görevini şu şekilde çalıştırırım:

rake 'app:compile:jammit'

kapistrano kendi komisyon değişkenini (hangi komisyonun kullanılacağını belirlemek için kullanılır) tanımladığı için bu çelişkiler ve bu nedenle, örneğin varlıkları önceden derleyen makbuzlarda yerleşik kesintiler
Michael

2

Bu benim için çalıştı:

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

O zaman sadece koş cap production "invoke[task_name]"


1

Çoğu yukarıdaki cevaptan kapistrano'dan herhangi bir komisyon görevini yürütmek için küçük bir iyileştirme ile

Capistrano'dan herhangi bir komisyon görevini çalıştırın

$ 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

1

Bu aynı zamanda çalışır:

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

Daha fazla bilgi: Capistrano Run


1
{deploy_to} / current burada çalışmaz. Sembolik bağ değişmedi. Tırmık görevini güncellerseniz, bu eski kodu çalıştıracaktır. Bunun yerine {release_path} kullanmayı düşünün.
Mark Redding

daha fazla bilgi spam mi?
hcarreras

1

Birden fazla argüman iletebilmek istiyorsanız, bunu deneyin (marinosbern'in cevabına göre):

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

O zaman aşağıdaki gibi bir görevi çalıştırabilirsiniz: cap production invoke["task","arg1","arg2"]


0

Bu yüzden bunun üzerinde çalışıyorum. iyi çalışmasını sağlar. Bununla birlikte, koddan gerçekten yararlanmak için bir biçimlendiriciye ihtiyacınız var.

Biçimlendirici kullanmak istemiyorsanız, sadece günlük düzeyini hata ayıklama moduna ayarlayın. Bu semalar 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

Bu, yukarıdaki kodla çalışmak için oluşturduğum biçimlendirici. Bu, sshkit'te yerleşik olan: textsimple'a dayanır, ancak özel görevleri çağırmanın kötü bir yolu değildir. Oh bu kadar çok sshkit gem'in en yeni sürümüyle çalışmıyor. 1.7.1 ile çalıştığını biliyorum. Bunu söylüyorum çünkü ana dal mevcut SSHKit :: Command yöntemlerini değiştirdi.

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

0

Önceki cevaplar bana yardımcı olmadı ve şunu buldum: http://kenglish.co/run-rake-tasks-on-the-server-with-capistrano-3-and-rbenv/

namespace :deploy do
  # ....
  # @example
  #   bundle exec cap uat deploy:invoke task=users:update_defaults
  desc 'Invoke rake task on the server'
  task :invoke do
    fail 'no task provided' unless ENV['task']

    on roles(:app) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, ENV['task']
        end
      end
    end
  end

end

görev kullanımınızı çalıştırmak için

bundle exec cap uat deploy:invoke task=users:update_defaults

Belki birisi için yararlı olur

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.