ฉันมี deploy.rb ที่สามารถปรับใช้แอปของฉันบนเซิร์ฟเวอร์ที่ใช้งานจริงได้
แอปของฉันมีงานคราดที่กำหนดเอง (ไฟล์. rake ในไดเร็กทอรี lib / งาน)
ฉันต้องการสร้างงานแคปที่จะรันงานคราดนั้นจากระยะไกล
ฉันมี deploy.rb ที่สามารถปรับใช้แอปของฉันบนเซิร์ฟเวอร์ที่ใช้งานจริงได้
แอปของฉันมีงานคราดที่กำหนดเอง (ไฟล์. rake ในไดเร็กทอรี lib / งาน)
ฉันต้องการสร้างงานแคปที่จะรันงานคราดนั้นจากระยะไกล
คำตอบ:
ชัดเจนมากขึ้นเล็กน้อยในของคุณ\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 ได้ที่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
run
นั้นจะใช้ได้กับ capistrano จนถึงเวอร์ชัน 2 จากเวอร์ชัน 3 นี่คือวิธีที่จะไป
Capistrano 3 Generic Version (รันงานคราดใด ๆ )
การสร้างคำตอบของ 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
ต้องมาจากอัญมณีรางคาปิสตราโน
rake args[:command]
ด้วย execute :rake, "#{args.command}[#{args.extras.join(",")}]"
คุณสามารถดำเนินการงานที่มีหลายอาร์กิวเมนต์ดังนี้: cap production invoke["task","arg1","arg2"]
cap staging invoke['task[arg1\,arg2]']
คุณสามารถส่งผ่านข้อโต้แย้งหลายเช่น ฉันชอบวิธีนี้กับวิธีที่คุณพูดถึงเพราะมันสะท้อนให้เห็นถึงการเรียกคราดจริง cap staging invoke['task1 task2[arg1] task3[arg2\,arg3]']
ด้วยวิธีนี้คุณยังสามารถโยงหลายงานซึ่งมักจะมีประโยชน์: ใช้ได้กับคราด 10.2.0 หรือใหม่กว่า
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
คือ gotcha - ตอนแรกฉันไม่ได้คิดถึงมันและคิดไม่ออกว่าทำไมงานถึงไม่ทำอะไรเลย
"cd #{deploy_to}/current && #{rake} <task_name> RAILS_ENV=production"
มีวิธีทั่วไปที่ "ใช้ได้" กับ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
top.run
แทนrun
top
วิธีการ ในกรณีที่เรากำหนดไว้run
ในเนมสเปซเดียวกันtop.run
จำเป็นต้องมีมิฉะนั้นก็ยังควรค้นหาระดับบนสุดrun
แม้ว่างานจะเป็นเนมสเปซก็ตาม ฉันพลาดอะไรไปหรือเปล่า? เกิดอะไรขึ้นในกรณีของคุณ?
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
ที่อนุญาตให้เรียกใช้งานคราดคล้ายกับการใช้วิธีการรัน (คำสั่ง)
หมายเหตุ: คล้ายกับสิ่งที่Dukeเสนอ แต่ฉัน:
มีเสื้อคลุมอัญมณีที่น่าสนใจที่ทำให้งานคราดของคุณพร้อมใช้งานเป็นงาน Capistrano ดังนั้นคุณสามารถเรียกใช้งานได้จากระยะไกล 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
RAILS_ENV=production
เพื่อRAILS_ENV=#{rails_env}
ให้สามารถทำงานบนเซิร์ฟเวอร์การแสดงละครของฉันได้เช่นกัน
นี่คือสิ่งที่ฉันใส่ใน deploy.rb เพื่อลดความซับซ้อนในการรันงานคราด มันเป็นกระดาษห่อง่ายๆรอบ ๆ วิธี run () ของ capistrano
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})
ข้อมูลเพิ่มเติม: 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["task","arg1","arg2"]
ดังนั้นฉันจึงได้ดำเนินการนี้ ตะเข็บทำงานได้ดี อย่างไรก็ตามคุณต้องมีตัวจัดรูปแบบเพื่อใช้ประโยชน์จากโค้ดจริงๆ
หากคุณไม่ต้องการใช้ฟอร์แมตเตอร์เพียงแค่ตั้งค่าระดับการบันทึกเป็นโหมดดีบัก 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
นี่คือฟอร์แมตเตอร์ที่ฉันสร้างขึ้นเพื่อใช้กับโค้ดด้านบน มันขึ้นอยู่กับ: textimple ที่สร้างขึ้นใน sshkit แต่ไม่ใช่วิธีที่ไม่ดีในการเรียกใช้งานแบบกำหนดเอง โอ้สิ่งนี้ใช้ไม่ได้กับ 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
คำตอบก่อนหน้านี้ไม่ได้ช่วยฉันและฉันพบสิ่งนี้: จาก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
บางทีมันอาจจะมีประโยชน์สำหรับใครบางคน
#{rake}
ตัวแปรของ capistrano ได้หรือไม่? ดูเหมือนว่าจะไม่ใช่ตัวเลือกที่ดีที่สุดเสมอไป