108

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

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

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

4

16 に答える 16

60

でもう少し明示的に、\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
于 2010-02-03T13:12:35.697 に答える
44

...数年後...

capistrano の rails プラグインを見てください

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
于 2013-12-10T21:59:34.560 に答える
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は落とし穴でした。最初は考えもしませんでしたし、タスクが何もしていない理由がわかりませんでした。

于 2008-11-23T06:46:08.080 に答える
20

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

require 'bundler/capistrano'rakeを変更する他の拡張機能と「うまく機能する」一般的な方法があります。マルチステージを使用している場合、これは実稼働前の環境でも機能します。要旨?可能であれば、configvarsを使用してください。

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
于 2012-05-08T01:37:32.910 に答える
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 タスクを実行できます。


注: Dukeが提案したものと似ていますが、私は:

  • 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!
于 2011-08-29T11:52:05.223 に答える
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 
于 2012-12-06T14:13:29.617 に答える
3

これは私のために働いた:

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

于 2015-12-23T07:18:00.377 に答える
2

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'
于 2011-06-14T23:31:34.070 に答える
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"]

于 2014-09-24T01:21:34.127 に答える
1

これも機能します:

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

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

于 2010-07-26T17:22:38.710 に答える
1

そのほとんどは上記の回答からのもので、capistrano から任意のレーキ タスクを実行するためのマイナーな機能強化が含まれています。

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
于 2013-07-04T06:33:03.760 に答える
0

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

フォーマッタを使用したくない場合は、ログ レベルをデバッグ モードに設定します。これらの semas to 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
于 2015-05-12T00:44:34.980 に答える