Capistranoからレーキタスクを実行するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/312214

  •  10-07-2019
  •  | 
  •  

質問

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

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

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

役に立ちましたか?

解決 2

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の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

Capistrano 3汎用バージョン(レーキタスクを実行)

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&quot; invoke [db:migrate]&quot;

deploy:set_rails_env が必要とするのはcapistrano-rails gemから来ていることに注意してください

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

「正常に機能する」一般的な方法があります。 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

を使用する

カスタムcapistranoレシピをいじらずに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タスクを実行できます。


注:デュークが提案しましたが、私は

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

おもしろい宝石 cape があります。これにより、レーキタスクを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&quot; invoke [task_name]&quot;

を実行します。

その大部分は上記の回答 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

複数の引数を渡すことができるようにしたい場合は、これを試してください(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 [&quot; task&quot;、&quot; arg1&quot;、&quot; arg2&quot;]

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

フォーマッタを使用したくない場合は、ログレベルをデバッグモードに設定するだけです。 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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top