Creating Cron Jobs in Ruby
Ruby is one of the most beloved programming languages of the web era. In no small part due to the popularity of the Rails framework, it's not surprising that Ruby is extensively used for writing cron jobs.
Before we continue, let's define what a cron job is. Originally, cron jobs were commands on a Linux/Unix server being executed on a schedule by the
cron scheduler. As software tools/frameworks have proliferated, a more modern definition is — a piece of code running in the background at a scheduled time.
One of the most ubiquitous characteristics of a cron job is the cron schedule syntax. The syntax —
*/4 1,5,7 22 * 0-2,6 — is reminiscent of regular expressions, and is very hard to remember.
In this article, you’ll learn how to run any Ruby script as a cron job. We'll also explore some popular Ruby libraries that make it easier to run cron jobs.
Run a Ruby script as a cron job
This script can be executed from the command prompt as:
It's useful to manually test any new script before running it as a cronjob. Even if you don't see any errors when running it directly, you will want to take a look at the important considerations listed below to understand some of the ways that cron jobs can silently fail.
Editing the Crontab
From the command line on your server, run
crontab -e to access your crontab in a text editor. From there, you can paste or write in your crontab entry to run your Ruby script. To run our cron job a midnight every day we will add the following line:
0 0 * * * ruby /path/to/script.rb
What the * * * * ?!?
The syntax for cron schedules is terse and tricky to remember. Our guide on Linux cron jobs covers cron syntax in detail.
Run cron jobs with the Whenever gem
While it's fairly easy to set up a simple example cron job, managing cron jobs can be tedious and error-prone. Writing and testing cron syntax can be difficult, especially for developers who are not familiar with the nuances of the Unix cron system. And trying to manage a large number of jobs without proper environments and version control can quickly turn to madness.
The whenever gem simplifies this process by allowing developers to define their cron jobs in Ruby code. Instead of writing complex cron syntax, developers can use a simple, readable DSL to define their jobs. Whenever then generates a proper crontab file and installs it on your server(s).
# execute a command every 5.minutes do command "/usr/bin/my_command" end
Whenever also makes it easy to manage cron jobs across multiple servers using the concept of roles. Developers can define sets of jobs for different sets of servers by assigning those servers "roles" (e.g.
db), and Whenever will generate separate cron files for each of those servers based on the assigned roles.
every :day, at: '1:37pm', roles: [:app] do rake 'app:task' # will only be added to crontabs of :app servers end every :hour, roles: [:db] do rake 'db:task' # will only be added to crontabs of :db servers end every :day, at: '12:02am' do command "run_this_everywhere" # will be deployed to :db and :app servers end
Run cron jobs with Sidekiq
Sidekiq is a popular library for running Ruby code in the background (asynchronously). Sidekiq enterprise, and the open-source
sidekiq-scheduler gem both provide ways to run cron jobs via Sidekiq instead of relying on crontab.
This has some big advantages over traditional cron jobs. The queue-based architecture of Sidekiq means that important jobs can be priorized, failed jobs retried and long-running/intensive jobs are (often) easier to scale horizontally.
# config/initializers/sidekiq.rb Sidekiq.configure_server do |config| # register any Jobs to be run on a cron based schedule config.periodic do |mgr| mgr.register "* * * * *", EveryMinuteJob, retry: 1 mgr.register "*/4 * 10 * *", OddlyTimedCriticalJob, queue: 'critical' end end
Monitor Ruby cron jobs
No matter which tool you use, it's important to consider how you will monitor your cron jobs — it's too easy for them to fail silently. That's where a tool like Cronitor comes in. Cronitor makes it easy to monitor your cron jobs, and will alert you immediately when a job fails, or doesn't run on time.
Cronitor has SDKs for both Ruby and Sidekiq that make it easy to add monitoring with just a couple of lines of code.
Monitoring Ruby Cron Jobs
# Sample Ruby configuration require 'cronitor' # everything within the block is monitored, # and errors are reported automatically Cronitor.job 'important-job' do ImportantJob.new(Date.today).run() end
Monitoring Sidekiq Cron Jobs
# config/initializers/sidekiq.rb Sidekiq.configure_server do |config| config.server_middleware do |chain| chain.add Sidekiq::Cronitor::ServerMiddleware end end # sync any cron job schedules to Cronitor Sidekiq::Cronitor::PeriodicJobs.sync_schedule!
If you are using Sidekiq, be sure to check out our complete guide to Sidekiq Monitoring