मैं Capistrano से एक रेक कार्य कैसे चलाऊँ?


105

मेरे पास पहले से ही एक तैनाती है। मेरे प्रोडक्शन सर्वर पर अपने ऐप को तैनात किया जा सकता है।

मेरे ऐप में एक कस्टम रेक कार्य (lib / कार्य निर्देशिका में एक .rake फ़ाइल) है।

मैं एक कैप टास्क बनाना चाहूंगा जो उस रेक कार्य को दूरस्थ रूप से चलाएगा।


2
क्या कोई कैपिसट्रानो के स्वयं के #{rake}चर का उपयोग करने के पेशेवरों / विपक्षों को समझा सकता है ? लगता है यह हमेशा सबसे अच्छा विकल्प नहीं है।
लुललाला

जवाबों:


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 रेक तो rvm setups सही रेक उठाएगा।
DGM

8
यदि उपलब्ध हो तो 'बंडल
एग्जीक्यूशन

44

... कुछ साल बाद ...

Capistrano के रेल प्लगइन पर एक नज़र डालें, आप 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 के लिए है।
फोल्केकर

बहुत मदद की। धन्यवाद! @ मिरेक रूसिन
निशांत श्रीवास्तव

अन्य उत्तर, यह प्रयोग run2 संस्करण तक capistrano पर काम करेगा। संस्करण 3 से यह जाने का रास्ता है।
डॉन ज्यूलियो

44

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 "invoke[db:migrate]"

ध्यान दें कि deploy:set_rails_envआवश्यकता होती है capistrano-rails मणि से


1
यह केवल एक ही तर्क का समर्थन करता है, यदि आप अपने rake args[:command] साथ प्रतिस्थापित करते हैं execute :rake, "#{args.command}[#{args.extras.join(",")}]" तो एक कार्य को कई तर्कों के साथ निष्पादित कर सकते हैं जैसे: cap production invoke["task","arg1","arg2"]
रॉबिन क्लॉवर्स 24'14

1
@ रॉबिन क्लोवर्स आप कई तर्क पारित कर सकते हैं, जैसे cap staging invoke['task[arg1\,arg2]']। मैं इस दृष्टिकोण को आपके द्वारा उल्लेखित पसंद करता हूं क्योंकि यह रेक के वास्तविक आह्वान को दर्शाता है। इस दृष्टिकोण के साथ आप कई कार्यों को भी श्रृंखलाबद्ध कर सकते हैं, जो अक्सर उपयोगी होता है cap staging invoke['task1 task2[arg1] task3[arg2\,arg3]']:। रेक
10.2.0

यह बहुत अच्छा है - मैं ध्यान देना चाहूंगा, आपको अपने सर्वर भूमिकाओं में से एक के रूप में शामिल करना होगा।
lfender6445

जाहिर तौर पर इसके लिए "आह्वान करना जरूरी था [db: migrate]" ... सुधार किया गया।
अब्राम

@ आपके द्वारा सुझाए गए आदेश के साथ मुझे "" पता नहीं कैसे कार्य का निर्माण करना है "आह्वान"
dc10 10

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
यदि आप कई सर्वरों पर तैनात हैं तो यह काम नहीं करेगा। यह कई बार रेक कार्य चलाएगा।
मार्क रेडिंग

4
वास्तव में "cd #{deploy_to}/current && #{rake} <task_name> RAILS_ENV=production"
कैपिस्ट्रानो

@ मर्क रिडिंग: क्या आप रेक कार्यों के लिए सर्वरों में से किसी एक को अपनी भूमिका में रख सकते हैं और अपने कैपिस्ट्रानो कार्य को केवल उस भूमिका वाले सर्वरों पर चलाने के लिए सीमित कर सकते हैं?
15:15 बजे mj1531

मैंने कुछ किया जहाँ मैंने अपनी तैनाती में एक कार्य बनाया। उस कार्य में a: रोल्स =>: db इस तरह है कि यह केवल उसी सर्वर पर निष्पादित होगा जिसे मैंने db के लिए मेरे प्राथमिक के रूप में परिभाषित किया है: माइग्रेट।
मार्क रेडिंग

20

कैपिस्ट्रानो-स्टाइल रेक इनवोकेशन का उपयोग करें

एक सामान्य तरीका है जो require 'bundler/capistrano'रेक को संशोधित करने वाले अन्य एक्सटेंशन के साथ "बस काम" करेगा । यदि आप मल्टीस्टेज का उपयोग कर रहे हैं तो यह पूर्व-उत्पादन वातावरण के साथ भी काम करेगा। सार? यदि आप कर सकते हैं तो कॉन्फ़िगर करें का उपयोग करें।

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
यह सबसे अच्छा समाधान है, जहां उपलब्ध केपिस्ट्रानो मूल्यों का उपयोग करता है
लूप जूल

2
संभवतः यह जोड़ने के लायक है कि यदि आपका कार्य नामांकित है (यानी शीर्ष स्तर के नामस्थान में परिभाषित नहीं है) तो आपको top.runइसके बजाय उपयोग करना पड़ सकता हैrun
dolzenko

धन्यवाद @dolzenko बस विधि के लिए डॉक्सtop मिले । उस मामले में जहां हमने runएक ही नामस्थान में परिभाषित किया है, top.runकी आवश्यकता है, अन्यथा यह अभी भी शीर्ष-स्तर को ढूंढना चाहिए runजहां कार्य को नाम दिया गया है। क्या मुझे कुछ याद आया? आपके मामले में क्या हुआ?
कप्तानी

1
मेरे पास स्पष्ट रूप से समान नामस्थान में कोई रन विधि परिभाषित नहीं है, इसलिए मुझे यकीन नहीं है कि मुझे इसकी आवश्यकता क्यों है। किसी भी मामले में कैपिस्ट्रानो 2.0 एक इतिहास है और अगला संस्करण रेक आधारित है (चीजों को अधिक उम्मीद के मुताबिक बनाने की उम्मीद है)
dolzenko

16

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

यह रन (कमांड) विधि का उपयोग करने के समान रेक कार्य चलाने की अनुमति देता है।


नोट: यह ड्यूक के प्रस्ताव के समान है , लेकिन मैं:

  • current_release के बजाय latest_release का उपयोग करें - मेरे अनुभव से यह अधिक है जो आप एक रेक कमांड चलाते समय उम्मीद करते हैं;
  • रेक और कैपिस्ट्रानो के नामकरण सम्मेलन का अनुसरण करें (इसके बजाय: cmd -> कार्य और रेक -> रन-क्रै)
  • RIDS_ENV = # {rails_env} सेट न करें क्योंकि इसे सेट करने का सही स्थान default_run_option चर है। जैसे default_run_options [: env] = {'RAILS_ENV' => 'उत्पादन'} # - # DRY!

5

एक दिलचस्प मणि केप है जो आपके रेक कार्यों को कैपिस्ट्रानो कार्यों के रूप में उपलब्ध करता है, जिससे आप उन्हें दूरस्थ रूप से चला सकते हैं। capeअच्छी तरह से प्रलेखित है, लेकिन यहाँ मैं कैसे सेट अप करने के लिए एक संक्षिप्त अवलोकन है।

मणि स्थापित करने के बाद, बस इसे अपनी config/deploy.rbफ़ाइल में जोड़ें ।

# config/deploy.rb
require 'cape'
Cape do
  # Create Capistrano recipes for all Rake tasks.
  mirror_rake_tasks
end

अब, आप rakeस्थानीय रूप से या दूरस्थ रूप से सभी कार्यों को चला सकते हैं cap

अतिरिक्त बोनस के रूप में, capeआपको यह निर्धारित करने की अनुमति देता है कि आप स्थानीय और दूरस्थ रूप से अपना रेक कार्य कैसे चलाना चाहते हैं (अधिक नहीं 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 के साथ संगत नहीं है।
नियाव

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}अनुमति देता है।
इवानमर्फी

2

यहाँ पर मैंने अपने रेकिंग कार्यों को सरल बनाने के लिए अपनी तैनाती में डाल दिया। यह कैपिस्ट्रानो के रन () विधि के आसपास एक साधारण आवरण है।

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'

कैपिस्ट्रानो के रूप में यह टकराव परिभाषित करता है कि यह स्वयं रेक वैरिएबल है (इसका उपयोग करने के लिए कौन सा रेक निर्धारित किया जाता है) और इस तरह से प्राप्तियों में निर्मित टूटता है उदाहरण के लिए, जो संपत्ति को दबाता है
माइकल

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 से कोई भी रेक कार्य चलाएं

$ 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
{तैनाती_तो} / करंट यहां काम नहीं करेगा। प्रतीकात्मक लिंक नहीं बदला है। यदि आप रेक कार्य को अपडेट करते हैं, तो यह पुराना कोड चलेगा। इसके बजाय {release_path} का उपयोग करने पर विचार करें।
मार्क रेडिंग

अधिक जानकारी स्पैम है?
15 अप्रैल को hcarreras

1

यदि आप कई तर्क पारित करने में सक्षम होना चाहते हैं तो यह प्रयास करें (मैरिनबर्सन के जवाब के आधार पर):

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

इसलिए मैं इस पर काम कर रहा हूं। यह अच्छी तरह से काम करता है। हालाँकि आपको कोड का वास्तव में लाभ उठाने के लिए एक फॉर्मेटर की आवश्यकता है।

यदि आप किसी फ़ॉर्मेटर का उपयोग नहीं करना चाहते हैं तो लॉग स्तर को डीबग मोड में सेट करें। ये सेमा टू एच

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 मणि के नवीनतम संस्करण के साथ काम नहीं करता है। मुझे पता है कि यह 1.7.1 के साथ काम करता है। मैं यह कहता हूं क्योंकि मास्टर ब्रांच ने SSHKit :: कमांड मेथड्स को बदल दिया है जो उपलब्ध हैं।

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

शायद यह किसी के लिए उपयोगी होगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.