実稼働サーバーにアプリをデプロイできるdeploy.rbが既にあります。
私のアプリにはカスタムrakeタスク(lib/tasksディレクトリにある.rakeファイル)が含まれています。
そのrakeタスクをリモートで実行するcapタスクを作成したいと思います。
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
は落とし穴だった-最初は考えもしなかったし、なぜタスクが何もしなかったのか理解できなかった。
\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 3 Generic Version(レーキタスクを実行)
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からのものです
...数年後...
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
require 'bundler/capistrano'
およびrakeを変更するその他の拡張機能で「機能する」一般的な方法があります。これは、マルチステージを使用している場合、運用前環境でも機能します。要旨?可能であれば、構成変数を使用します。
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をインストールし、次のようにリモートサーバーで目的の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タスクを実行できます。
注: Duke が提案したものに似ていますが、私は:
興味深いgem cape があります。これにより、RakeタスクがCapistranoタスクとして利用可能になり、リモートで実行できます。 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
以下は、rakeタスクの実行を簡素化するためにdeploy.rbに入れたものです。これは、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]"
を実行します
複数の引数を渡すことができるようにしたい場合は、これを試してください(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"]
そのほとんどは 上記の回答 からのもので、capistranoからrakeタスクを実行するためのマイナーな機能強化があります
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 Run
だから私はこれに取り組んでいます。うまく機能します。ただし、コードを実際に活用するにはフォーマッターが必要です。
フォーマッタを使用したくない場合は、ログレベルをデバッグモードに設定するだけです。 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で動作することを知っています。マスターブランチが利用可能な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