Rails 中如何运行定时(cron)任务?

Rails 跑定时任务的标准方案:whenever gem 用 Ruby 语法定义调度并生成 crontab;附 schedule.rb 示例、部署更新命令、rake runner/job 三种任务类型与 FAQ。

最佳实践
Rails 中如何运行定时(cron)任务?封面

whenever gem:在 config/schedule.rb 里用 Ruby DSL 写调度,whenever --update-crontab 把它编译成系统 crontab。 调度定义跟代码一起进版本库、随部署更新,比在服务器上手改 crontab 可靠得多。

1. 安装

# Gemfile
gem 'whenever', require: false
bundle install
bundle exec wheneverize .    # 生成 config/schedule.rb

2. 定义调度(config/schedule.rb)

# 每天凌晨 2 点清理过期会话
every 1.day, at: '2:00 am' do
  rake 'sessions:cleanup'
end

# 每 10 分钟同步一次数据
every 10.minutes do
  runner 'SyncService.call'
end

# 每周一生成报表(ActiveJob)
every :monday, at: '6:30 am' do
  job 'WeeklyReportJob.perform_later'
end

三种任务类型:

  • rake:执行 Rake 任务(最常用的收口方式,逻辑写在 lib/tasks/)。
  • runner:跑一段 Rails 环境内的 Ruby 代码。
  • command / job:裸 shell 命令或 ActiveJob。

3. 写入 crontab

whenever --update-crontab          # 编译并写入当前用户 crontab
crontab -l                         # 查看生成结果

生成的规则带 whenever 的注释标记,下次更新会精确替换自己管理的段落,不影响其他条目。

4. 部署集成

Capistrano 在 deploy.rb 里加:

set :whenever_command, 'bundle exec whenever'
require 'whenever/capistrano'

每次部署自动刷新 crontab。其他部署方式(Docker/K8s)则注意:只有一份实例该跑 whenever 更新,多副本同时注册同一批任务会重复执行——常见做法是单独一个 "scheduler" 角色容器。

观测云对照

Rails 定时任务失败的典型路径是 rake 任务抛异常——日志有了,但没人看。把 Rails 日志和任务输出统一采集到观测云,对任务名做心跳式监控:预期窗口内没有成功记录就告警;Ruby 应用再接入观测云 APM,任务里慢查询、外部调用超时都能关联到具体代码行。

常见问题(FAQ)

Q:改了 schedule.rb 后任务没变?
A:schedule.rb 只是源文件,必须重跑 whenever --update-crontab 才会写进系统 crontab。

Q:服务器上任务的时区不对?
A:whenever 用的是系统时间。在 schedule.rb 顶部可设 set :chronic_options, hours24: true 之类辅助解析,但时区本身跟着 OS 走——Docker 镜像里记得设 TZ

Q:能从 crontab 里移除 whenever 管理的条目吗?
A:whenever --clear-crontab 清除它写入的全部条目。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台