カピストラーノからレーキタスクを実行するにはどうすればよいですか?


105

アプリを本番サーバーにデプロイできるdeploy.rbがすでにあります。

私のアプリにはカスタムのrakeタスク(lib / tasksディレクトリの.rakeファイル)が含まれています。

rakeタスクをリモートで実行するcapタスクを作成したいと思います。


2
誰かがカピストラーノ自身の#{rake}変数を使用することの長所/短所を説明できますか?それは常に最良の選択肢ではないようです。
lulalala

回答:


59

もう少し明示的に、で、\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

1
/ usr / bin / env rakeを使用する方が良いので、rvmセットアップは正しいrakeを取得します。
DGM 2010年

8
「bundle exec」が利用可能な場合
Bogdan Gusiev

44

...数年後...

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

3
これはcapistrano v3専用です。
phillbaker 2014年

たくさん助けました。ありがとう!@Mirek Rusin
Nishant Shrivastava

他の返信は、その使用runはバージョン2までのカピストラーノで機能します。バージョン3からこれが進むべき道です。
Don Giulio、

44

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_envrequireはcapistrano-rails gemから来ることに注意してください


1
これは、あなたが交換した場合、単一の引数をサポート rake args[:command] して execute :rake, "#{args.command}[#{args.extras.join(",")}]" 複数の引数を持つタスクを実行することができますので、好き: cap production invoke["task","arg1","arg2"]
ロビンClowers

1
@ Robin Clowersたとえば、複数の引数を渡すことができcap staging invoke['task[arg1\,arg2]']ます。レーキの実際の呼び出しを反映しているので、私はあなたが言及したものよりもこのアプローチを好みます。このアプローチを使用すると、複数のタスクを連鎖させることもできますcap staging invoke['task1 task2[arg1] task3[arg2\,arg3]']。これは、多くの場合に役立ちます。レーキ10.2.0以降で動作
marinosb

これはすばらしいことです。サーバーの役割の1つとして:appを含める必要があります。
lfender6445 2015年

どうやらこれは "invoke [db:migrate]"である必要があった...修正が行われた。
エイブラム2015

@Abramが提案したコマンドを使用して、「タスク 'invoke」のビルド方法がわからない
dc10

41
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は落とし穴でした-最初はそれを考えていなかったので、タスクが何も実行していない理由を理解できませんでした。


2
小さな改善:セミコロンを&&で置き換えると、最初のステートメント(ディレクトリの変更)が失敗した場合、2番目のステートメント(rakeタスクを実行)は実行されません。
テフロンテッド

2
複数のサーバーに展開している場合、これは機能しません。rakeタスクを複数回実行します。
マークレディング2011年

4
カピストラーノのレーキ設定を本当に尊重する必要があります"cd #{deploy_to}/current && #{rake} <task_name> RAILS_ENV=production"
カレス

@Mark Redding:サーバーの1つを独自の役割でrakeタスクに割り当て、その役割を持つサーバーでのみ実行するようにcapistranoタスクを制限できますか?
mj1531

私は自分のdeploy.rbでタスクを作成する場所で何かをしました。そのタスクには:roles =>:dbがあり、db:migrateのプライマリとして定義したのと同じサーバーでのみ実行されます。
マークレディング

20

カピストラーノスタイルのレイク呼び出しを使用する

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

2
これは最も優れたソリューションであり、可能な場合はcapistrano値を使用します
loopj

2
タスクに名前空間が付けられている(つまり、最上位の名前空間で定義されていない)場合は、top.run代わりに使用する必要がある可能性があることを追加する価値があると考えられますrun
dolzenko

@dolzenkoに感謝します。メソッドドキュメントをtop見つけました。run同じ名前空間で定義したtop.run場合は必須ですが、それ以外の場合runは、タスクが名前空間である場合でもトップレベルを見つける必要があります。私は何かを見逃しましたか?あなたの場合はどうなりましたか?
captainpete 2013年

1
同じ名前空間でrunメソッドが定義されていないことは明らかなので、なぜそれが必要なのかはわかりません。いずれにしても、Capistrano 2.0は歴史であり、次のバージョンはRakeベースです(物事をより予測可能にすることを期待しています)
dolzenko

16

capistrano-rake宝石を使う

カスタムのカピストラーノレシピをいじらずにgemをインストールし、次のようにリモートサーバーで目的のrakeタスクを実行します。

cap production invoke:rake TASK=my:rake_task

完全開示:私が書いた


7

私は本番で次のようなヘルパーメソッドを使用しています。

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

これにより、run(コマンド)メソッドを使用するのと同じようにrakeタスクを実行できます。


注:デュークが提案したものと似ていますが、私は次のようにしています。

  • current_releaseの代わりにlatest_releaseを使用してください-私の経験から、rakeコマンドを実行するときに期待する以上のものです。
  • RakeとCapistranoの命名規則に従います(cmd-> taskおよびrake-> run_rakeの代わり)
  • RAILS_ENV =#{rails_env}を設定しないでください。これを設定する適切な場所はdefault_run_options変数です。たとえば、default_run_options [:env] = {'RAILS_ENV' => 'production'}#-> DRY!

5

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

追加のボーナスとして、caperakeタスクをローカルおよびリモートで実行する方法を設定できます(これ以上はありません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'

注:Capistrano v2.xでのみ機能します。Capistrano v3との互換性はありません。
nayiaw 2015年

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
良い。からRAILS_ENV=productionに変更するとRAILS_ENV=#{rails_env}、ステージングサーバーでも機能するようになります。
evanrmurphy 2013年

2

以下は、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'

capistranoが独自のレーキ変数(どのレーキを使用するかを決定するために使用される)を定義するため、これは競合します。たとえば、資産をプリコンパイルするものなどの組み込みのレシーブを壊します
Michael

2

これは私のために働きました:

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]"


1

それのほとんどは上の答えからです、カピストラーノからレーキタスクを実行するためのマイナーな拡張を含むからです

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

1

これも機能します:

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

詳細:カピストラーノラン


1
{deploy_to} / currentはここでは機能しません。シンボリックリンクは変更されていません。rakeタスクを更新すると、古いコードが実行されます。代わりに{release_path}の使用を検討してください。
マークレディング2011年

より多くの情報はスパムですか?
hcarreras 2014

1

複数の引数を渡せるようにしたい場合は、これを試してください(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"]


0

だから私はこれに取り組んできました。うまく機能するように縫い合わせています。ただし、実際にコードを利用するにはフォーマッタが必要です。

フォーマッターを使用しない場合は、ログレベルをデバッグモードに設定します。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

0

以前の答えは私を助けませんでした、そして私はこれを見つけました: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

多分それは誰かのために役立つでしょう

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.