Managing CRON jobs the Ruby way



2009/11/30 // Leeds // // Feed



CRON jobs have always been a bit of a pain to manage. Whilst the syntax isn’t the most difficult to calculate it would be nice to have an easier way to describe the intervals at which tasks should run. Even more so the schedules should be managed alongside your other project code, as one undoubtably requires the other to run (such as Rake tasks). Lots of people have written gems and plugins to scratch this itch, one of them being whenever.

Whenever provides a really tidy DSL to declare your CRON jobs in natural Ruby syntax. A basic example looks like this:

  set :output, File.join("log", "cron.log")
  
  every 1.day do
    rake "mailer:enqueue_daily"
  end

Running the whenever command from your Rails project directory then produces the desired CRON syntax:

  # => 0 0 * * * cd /path/to/app && RAILS_ENV=production /usr/bin/env rake mailer:enqueue_daily >> log/cron.log 2>&1

This worked really well for me however I prefer to have my environment specific configurations in separate files. Although the wiki provided a way to do this it didn’t feel very clean. A simple fix to this would be to load an environment specific file if it exists:

  set :output,   File.join("log", "#{@environment}_cron.log")
  set :env_file, File.join("config", "schedule", "#{@environment}.rb")

  # Global jobs
  every 1.day do
     rake "mailer:enqueue_daily"
  end

  # Load environment specific jobs
  load(@env_file) if File.exists?(@env_file)

Therefore running whenever --set environment=staging would load RAILS_ROOT/config/schedule/staging.rb with your staging environment specific jobs and output the result to log/staging_cron.log. You can also easily integrate this into a Capistrano task when you deploy new code:

  desc "Update the crontab file from the rules within config/schedule.rb"
  task :update_crontab, :roles => :db do
    run "cd #{release_path} && whenever --update-crontab #{application} --set environment=#{rails_env}"
  end

It’s tools like these that make maintaining larger applications that little bit easier.

Other (possibly related) posts

Comments