回答:
もう少し明示的に、で、\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
run
はバージョン2までのカピストラーノで機能します。バージョン3からこれが進むべき道です。
Capistrano 3 Generic Version(Rakeタスクを実行します)
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
requireはcapistrano-rails gemから来ることに注意してください
rake args[:command]
して execute :rake, "#{args.command}[#{args.extras.join(",")}]"
複数の引数を持つタスクを実行することができますので、好き: cap production invoke["task","arg1","arg2"]
cap staging invoke['task[arg1\,arg2]']
ます。レーキの実際の呼び出しを反映しているので、私はあなたが言及したものよりもこのアプローチを好みます。このアプローチを使用すると、複数のタスクを連鎖させることもできますcap staging invoke['task1 task2[arg1] task3[arg2\,arg3]']
。これは、多くの場合に役立ちます。レーキ10.2.0以降で動作
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
は落とし穴でした-最初はそれを考えていなかったので、タスクが何も実行していない理由を理解できませんでした。
"cd #{deploy_to}/current && #{rake} <task_name> RAILS_ENV=production"
require 'bundler/capistrano'
レーキを変更する他の拡張機能と「そのまま動作する」一般的な方法があります。マルチステージを使用している場合、これは運用前環境でも機能します。要旨?可能であれば、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
top.run
代わりに使用する必要がある可能性があることを追加する価値があると考えられますrun
top
見つけました。run
同じ名前空間で定義したtop.run
場合は必須ですが、それ以外の場合run
は、タスクが名前空間である場合でもトップレベルを見つける必要があります。私は何かを見逃しましたか?あなたの場合はどうなりましたか?
capistrano-rake
宝石を使うカスタムのカピストラーノレシピをいじらずにgemをインストールし、次のようにリモートサーバーで目的の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(コマンド)メソッドを使用するのと同じようにrakeタスクを実行できます。
注:デュークが提案したものと似ていますが、私は次のようにしています。
rakeタスクをCapistranoタスクとして利用できるようにする興味深いgem capeがあり、リモートで実行できます。cape
は十分に文書化されていますが、ここではiの設定方法の簡単な概要を示します。
gemをインストールしたら、これをconfig/deploy.rb
ファイルに追加します。
# config/deploy.rb
require 'cape'
Cape do
# Create Capistrano recipes for all Rake tasks.
mirror_rake_tasks
end
これで、すべてのrake
タスクをローカルまたはリモートで実行できますcap
。
追加のボーナスとして、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
RAILS_ENV=production
に変更するとRAILS_ENV=#{rails_env}
、ステージングサーバーでも機能するようになります。
以下は、rakeタスクの実行を簡略化するためにdeploy.rbに追加したものです。これは、カピストラーノの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 'app:compile:jammit'
これも機能します:
run("cd #{release_path}/current && /usr/bin/rake <rake_task_name>", :env => {'RAILS_ENV' => rails_env})
詳細:カピストラーノラン
複数の引数を渡せるようにしたい場合は、これを試してください(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"]
だから私はこれに取り組んできました。うまく機能するように縫い合わせています。ただし、実際にコードを利用するにはフォーマッタが必要です。
フォーマッターを使用しない場合は、ログレベルをデバッグモードに設定します。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
これは、上記のコードを処理するために作成したフォーマッターです。これは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
以前の答えは私を助けませんでした、そして私はこれを見つけました: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
タスクを実行するには
bundle exec cap uat deploy:invoke task=users:update_defaults
多分それは誰かのために役立つでしょう
#{rake}
変数を使用することの長所/短所を説明できますか?それは常に最良の選択肢ではないようです。