كيف يمكنني تشغيل مهمة أشعل النار من Capistrano؟

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

  •  10-07-2019
  •  | 
  •  

سؤال

لدي بالفعل Deploy.rb يمكنه نشر تطبيقي على خادم الإنتاج الخاص بي.

يحتوي تطبيقي على مهمة rake مخصصة (ملف .rake في دليل lib/tasks).

أرغب في إنشاء مهمة قصوى من شأنها تشغيل مهمة أشعل النار هذه عن بعد.

هل كانت مفيدة؟

المحلول 2

run("cd #{deploy_to}/current && /usr/bin/env rake `<task_name>` RAILS_ENV=production")

وجدت أنه مع جوجل - 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

... بضع سنوات في وقت لاحق ...

وإلقاء نظرة على القضبان المساعد كابيسترانو، ويمكنك ان ترى على الموقع 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 النسخة العامة (تشغيل أي مهمة أشعل النار)

بناء نسخة عامة من إجابة ميريك روسين:

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

الدعاء

على غرار كابيسترانو استخدام أشعل النار

وهناك وسيلة مشتركة التي سوف "تعمل فقط" مع 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

استخدم capistrano-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

يسمح ذلك بتشغيل مهمة أشعل النار مشابهة لاستخدام طريقة التشغيل (الأمر).


ملحوظة:إنه مشابه لما دوق اقترحت ولكني:

  • استخدم last_release بدلاً من current_release - من تجربتي، فهو أكثر ما تتوقعه عند تشغيل أمر rake؛
  • اتبع اصطلاح التسمية لـ Rake وCapistrano (بدلاً من:cmd -> المهمة وأشعل النار -> run_rake)
  • لا تقم بتعيين RAILS_ENV=#{rails_env} لأن المكان المناسب لتعيينه هو المتغير default_run_options.على سبيل المثال، default_run_options[:env] = {'RAILS_ENV' => 'production'} # -> جاف!

وهناك جوهرة اهتمام الرأس الذي يجعل المهام أشعل النار الخاص بك كما تتوفر المهام كابيسترانو، حتى تتمكن من تشغيلها عن بعد. 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'
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 

وإليك ما وضعت في بلدي deploy.rb لتبسيط تشغيل المهام أشعل النار. انها المجمع بسيط حول طريقة كابيسترانو في المدى ().

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'

وهذا عمل بالنسبة لي:

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

معظمها من فوق الجواب مع تحسين بسيط لتشغيل أي مهمة أشعل النار من 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

وهذا يعمل أيضا:

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

ومزيد من المعلومات: كابيسترانو تشغيل

إذا كنت تريد أن تكون قادرة على تمرير الوسائط المتعددة تحاول هذه (على أساس الإجابة 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"]

وهكذا لقد تم العمل على هذا. من طبقات للعمل بشكل جيد. ومع ذلك كنت في حاجة الى formater أن تأخذ حقا الاستفادة من التعليمات البرمجية.

إذا كنت لا ترغب في استخدام المنسق مجرد تعيين مستوى السجل إلى وضع التصحيح. هذه semas إلى 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

وهذا هو المنسق لقد بنيت للعمل مع رمز أعلاه. وهو يقوم قبالة: textsimple صلب sshkit ولكنها ليست وسيلة سيئة لاستدعاء المهام المخصصة. يا هذا كثير لا يعمل مع الإصدار الأحدث من الأحجار الكريمة 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top