如何在Capistrano部署时让Rails的whenever gem仅在生产环境(而非预发布环境)写入crontab?
解决Whenever + Capistrano 环境特定定时任务的最简方案
我太懂这种卡在基础需求上的挫败感了——明明是合理的场景,试了一堆方法却没效果,确实闹心!下面给你一套经过验证、简洁有效的配置方式,保证能把定时任务牢牢绑定到对应环境:
方法一:在schedule.rb中直接做环境判断(最直观)
这是最直接的写法,不需要额外拆分文件,一眼就能看明白哪些任务属于哪个环境:
# config/schedule.rb set :output, "log/cron_log.log" set :whenever_identifier, "#{fetch(:application)}_#{fetch(:stage)}" # 给不同环境的crontab加前缀,避免冲突 # 仅生产环境执行的任务 if environment == 'production' every 1.day, at: '3:00 am' do runner "ProductionOnlyBatchJob.perform_later" end every :monday, at: '9:00 am' do rake "production:weekly_report" end end # 预发布和生产都需要执行的通用任务(可选) every :hour do runner "SystemHealthCheck.perform_later" end
方法二:拆分环境专属的任务文件(更清晰,适合任务多的场景)
如果你的定时任务数量很多,拆分到单独的环境文件里会更易维护:
先创建环境专属的任务目录和文件:
config/ schedule/ production.rb staging.rb主schedule.rb里加载对应环境的文件:
# config/schedule.rb set :output, "log/cron_log.log" set :whenever_identifier, "#{fetch(:application)}_#{fetch(:stage)}" # 动态加载当前环境的任务配置 load File.expand_path("../schedule/#{environment}.rb", __FILE__)在
config/schedule/production.rb里写生产专属任务,staging.rb里写预发布的(如果预发布不需要定时任务,就留空文件):# config/schedule/production.rb every 1.day, at: '3:00 am' do runner "ProductionOnlyBatchJob.perform_later" end
配合Capistrano的关键配置
不管用上面哪种方法,都要在Capistrano的环境配置里明确指定whenever的环境,避免混淆:
在
Capfile里确保加载whenever的Capistrano集成:# Capfile(Capistrano 3+版本) require 'whenever/capistrano3' # 如果是旧版Capistrano,用require 'whenever/capistrano'在
config/deploy/production.rb和config/deploy/staging.rb里添加:# config/deploy/production.rb & config/deploy/staging.rb set :whenever_environment, fetch(:stage)
最后一步:清理旧的crontab条目
因为之前可能已经在预发布服务器上写入了错误的任务,部署新配置后,手动清理一次对应环境的crontab:
# 在预发布服务器上执行 whenever --clear-crontab --set 'environment=staging&whenever_identifier=你的应用名_staging'
之后重新部署,预发布环境的crontab里就只会有你指定的任务(如果有的话),生产专属任务绝对不会跑进去了。
内容的提问来源于stack exchange,提问作者David Krider
相关产品推荐
相关产品推荐

