Frage

Ich habe bereits ein deploy.rb, dass mein App auf meinem Produktions-Server bereitstellen kann.

Meine app enthält eine benutzerdefinierte Rake-Task (eine .rake Datei im lib / Aufgaben Verzeichnis).

Ich möchte eine Kappe Aufgabe erstellen, die remote, dass Rake Task ausgeführt wird.

War es hilfreich?

Lösung 2

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

Gefunden es mit Google - http : //ananelson.com/said/on/2007/12/30/remote-rake-tasks-with-capistrano/

Die RAILS_ENV=production war ein Gotcha - ich zuerst nicht daran gedacht und kann nicht herausfinden, warum die Aufgabe nichts zu tun

.

Andere Tipps

Ein wenig deutlicher, in Ihrem \config\deploy.rb, fügen außerhalb jeder Aufgabe oder Namespace:

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

Dann von /rails_root/, können Sie ausführen:

cap staging rake:invoke task=rebuild_table_abc

... Einige Jahre später ...

Haben Sie einen Blick auf Capistrano des Schienen-Plugin, können Sie unter https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/migrations.rake#L5-L14 es etwas aussehen kann:

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 Generikums (laufen alle Rake-Task)

Der Aufbau eine generische Version von Mirek Rusin Antwort:

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

Beispiel Nutzung: cap staging "invoke[db:migrate]"

Beachten Sie, dass deploy:set_rails_env erfordert stammt aus dem Capistrano-Schienen gem

Mit Capistrano-Stil Rake Anrufungen

Es gibt einen gemeinsamen Weg, der würde mit require 'bundler/capistrano' und anderen Erweiterungen „einfach funktionieren“, die Harke ändern. Dies funktioniert auch mit der Vorproduktion Umgebungen, wenn Sie mehrstufige verwenden. Der Kern? Verwenden Config Vars, wenn Sie können.

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

Mit der capistrano-rake gem

Sie einfach das Juwel installieren, ohne mit benutzerdefinierten Capistrano Rezepten Messing und gewünschte Rake Aufgaben auf Remote-Servern wie folgt ausgeführt werden:

cap production invoke:rake TASK=my:rake_task

Full Disclosure: Ich habe es geschrieben

ich persönlich in der Produktion eine Hilfsmethode wie folgt verwenden:

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

Das erlaubt ähnliche Rake Aufgabe ausgeführt werden soll, um mit dem Lauf (Befehl) Methode.


Hinweis: Es ist ähnlich dem, was Duke vorgeschlagen, aber ich:

  • verwenden latest_release statt current_release - aus meiner Erfahrung ist es, was Sie erwarten, wenn ein Rake-Befehl ausgeführt wird;
  • folgen der Namenskonvention von Rake und Capistrano (statt: cmd -> Aufgabe und Rechen -> run_rake)
  • nicht festlegen RAILS_ENV = # {RAILS_ENV}, weil der richtige Ort, um festgelegt es die default_run_options variabel ist. Z. B default_run_options [: env]! = { 'RAILS_ENV' => 'Produktion'} # -> DRY

Es ist ein interessantes Juwel Kap , die Ihre Rake Aufgaben als Capistrano Aufgaben machen, damit Sie sie laufen können entfernt. cape ist gut dokumentiert, aber hier ist ein kurzer Überblick darüber, wie ich einzurichten.

Nach dem Juwel der Installation nur diese Datei auf Ihrem config/deploy.rb hinzuzufügen.

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

Jetzt können Sie laufen alle Aufgaben lokal oder remote über rake cap.

Als zusätzlichen Bonus, cape können Sie einstellen, wie Sie möchten, dass Ihre Rake Aufgabe lokal als auch remote auszuführen (nicht mehr bundle exec rake), nur fügen Sie diese zu Ihrer config/deploy.rb-Datei:

# 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 

Hier ist, was ich in meinem deploy.rb setzen Aufgaben Harke zu vereinfachen läuft. Es ist ein einfacher Wrapper um Capistrano run () -Methode.

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

Dann laufe ich einfach jede Rake Aufgabe wie folgt:

rake 'app:compile:jammit'

Das funktioniert für mich:

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

Dann einfach laufen cap production "invoke[task_name]"

Das meiste ist von oben Antwort mit einer geringfügigen Verbesserung jeder Rake Aufgabe von Capistrano ausführen

Ausführen beliebige Rake Aufgabe von Capistrano

$ 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

Dies funktioniert auch:

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

Mehr Infos: Capistrano Run

Wenn Sie wollen in der Lage sein, dies mehr Argumente übergeben versuchen (basierend auf marinosbern Antwort):

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

Dann können Sie eine Aufgabe ausführen, wie so: cap production invoke["task","arg1","arg2"]

So habe ich gearbeitet, zu diesem Thema. es Nähte gut zu funktionieren. Allerdings benötigen Sie einen formater wirklich Vorteil des Codes zu nehmen.

Wenn Sie nicht möchten, dass ein Formatierer verwenden, nur die Protokollebene auf den Debug-Modus. Diese semas zu 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

Dies ist die Forma ich mit dem Code oben arbeiten gebaut. Es basiert aus den: textsimple in die sshkit gebaut, aber es ist keine schlechte Art und Weise kundenspezifische Aufgaben aufzurufen. Oh, das viele funktioniert nicht mit der neuesten Version von sshkit gem. Ich weiß, es mit 1.7.1 funktioniert. Ich sage das, weil der Master-Zweig hat die SSHKit :: Befehl Methoden geändert, die verfügbar sind.

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top