Wie kann ich einen Rechen Aufgabe von Capistrano laufen?
-
10-07-2019 - |
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.
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