How to Schedule Cron Jobs in Ruby With the Whenever Gem

What is Cron?

Cron is a job scheduling system available in Linux & MacOS operating systems.

It can be used to run any program at any given time.

This includes Ruby code!

If there is a specific recurring task that you would like to run automatically every day, every week or even every hour, then Cron may be what you’re looking for.

Example of tasks include:

  • Running a weekly database backup
  • Generating a daily report of website activity
  • Sending reminder emails

Let’s discover how you can make cron work for you!

Basics Of Cron

Every user can have a cron file where you define the tasks you want to run.

You can edit this file with the crontab -e command.

Or list scheduled tasks with crontab -l.

Example cron job:

0 0 * * * /opt/rubies/ruby-2.5.1/bin/rake db:backup

The syntax can be a bit tricky & you may not want to edit these files by hand all the time.

Are there any gems to make things easier for us?

Yes!

How to Use The Whenever Gem

Because cron syntax can be hard to remember we can use a gem like whenever.

This gem helps you define cron jobs in Ruby.

Install the gem first.

Then, create the configuration file:

wheneverize .
# [add] config/schedule.rb

Open it up.

You’ll see some commented-out examples, delete them if you want.

Let’s say we want a backup job that runs every hour.

Write this inside the “config/schedule.rb” file:

every 1.hour do
  rake "db:backup"
end

Options include:

  • rake (start a rake task defined on your current project, note that db:backup isn’t defined by default, but you can try db:version)
  • runner (Ruby class + method, like Archive.backup_now)
  • command (system command)

Now:

Run the whenever --update-crontab command to generate the cron entries.

You should be able to see your new entry with crontab -l.

This is what I got:

0 * * * * /bin/bash -l -c 'cd /home/jesus/testing && RAILS_ENV=production bundle exec rake db:backup --silent'

Notice that the task will run in production mode.

Want to change that?

You can use this setting:

set :environment, "development"

This goes in your schedule.rb file, at the top.

You can also use this command:

whenever --update-crontab --set environment=development

This creates all the tasks with “development” as the environment when you run this command.

More Whenever Examples

This example shows how you can be more specific.

Weekly task:

every :monday, at: "6:00 PM" do
  runner "Mail.send_weekly_newsletter"
end

This example shows how to run the same task multiple times during the day.

Run task twice a day:

every :day, at: ["12:00 AM", "12:00 PM"] do
  command "rm tmp/testing.txt"
end

Whenever Gem Logging & Troubleshooting

Once you have tasks in your crontab file (check with crontab -l) you’re ready to go.

Next:

How do you know if the scheduled tasks are working correctly?

You can set up logging & read the output.

Enable logging by adding this at the top of your schedule.rb file.

Configuration:

set :output, "log/cron.log"

Remember to run the whenever --update-crontab command every time you make changes!

Log file still empty?

You’ll have to wait the scheduled time to see something happen.

Btw, if you see this error in the logs:

/bin/bash: bundle: command not found

That means cron isn’t running the same version of Ruby that you’re.

If you’re using a Ruby version manager:

Make sure to load it from the .bash_profile file, instead of .bashrc, so your cron tasks can use it.

Alternatives to Whenever

Whenever is a well-maintained gem & it works great.

But what are the alternatives?

Here’s a list:

  • Heroku Scheduler, it’s a free job scheduling add-on for Heroku users. Not as flexible as cron itself but it gets things done
  • Rufus Scheduler, a Ruby gem that replaces cron with an in-memory scheduler
  • Sidecloq & Sidekiq-cron, both are Sidekiq add-ons that add recurring tasks to Sidekiq

Note that both Sidekiq addons want actual cron syntax for scheduling, so it won’t be as nice as whenever syntax.

The good thing is that they integrate with Sidekiq web UI.

Summary

You’ve learned how to schedule cron jobs using the whenever gem in Ruby!

Please share this article so more people can benefit from it.

Thanks for reading.

2 thoughts on “How to Schedule Cron Jobs in Ruby With the Whenever Gem”

  1. Might I suggest another alternative: delayed_job. It’s a direct extraction from Shopify where the job table is responsible for a multitude of core tasks.

    • Thanks for your suggestion, Rick!

      I didn’t know about this gem, but it looks like it’s more aimed at being a background queue type of thing, more than running scheduled jobs that repeat.

Comments are closed.