What is a cron expression? Syntax, examples, cheat sheet
A cron expression is a compact way to describe how often a scheduled task should run. On Linux, cron expressions live in a crontab file; on Windows, Task Scheduler hides them behind a graphical interface. Same concept.
You'll encounter cron expressions whenever you configure cron job monitoring in Oh Dear, so let's break down how to read them.
Finding your existing cron jobs #
To see cron jobs on your Linux server, connect via SSH and run:
$ crontab -l * * * * * php /var/www/artisan schedule:run
Each line represents one scheduled job. A couple of caveats:
- Every user on the server has their own crontab.
crontab -lshows only the one for the user you're currently logged in as. For example, jobs running aswww-datawon't appear if you SSH in asubuntu. - System-wide cron jobs can also live in
/etc/cron.d/,/etc/cron.hourly/,/etc/cron.daily/,/etc/cron.weekly/, and/etc/cron.monthly/.
Reading the syntax #
A cron expression has five fields that describe when to run, followed by the command to execute:
┌───────────── minute (0 - 59) │ ┌───────────── hour (0 - 23) │ │ ┌───────────── day of month (1 - 31) │ │ │ ┌───────────── month (1 - 12) │ │ │ │ ┌───────────── day of week (0 - 6, Sunday to Saturday, │ │ │ │ │ 7 is also Sunday on some systems) │ │ │ │ │ * * * * * <command>
Worked example #
0 */4 * * * logrotate
Reading each field:
- minute:
0— at minute 0 - hour:
*/4— every hour that's divisible by 4 (00, 04, 08, 12, 16, 20) - day of month:
*— every day - month:
*— every month - day of week:
*— every day of the week
So logrotate runs every 4 hours, at the start of the hour (00:00, 04:00, 08:00, ...).
The most common pattern #
* * * * * <command>
Five asterisks means "every minute, every hour, every day". You'll see this a lot on Laravel apps that run php artisan schedule:run every minute.
Common cron expressions #
| Expression | Runs |
|---|---|
* * * * * |
Every minute |
*/5 * * * * |
Every 5 minutes |
*/15 * * * * |
Every 15 minutes |
0 * * * * |
Every hour, on the hour |
0 */4 * * * |
Every 4 hours |
0 0 * * * |
Every day at midnight |
0 2 * * * |
Every day at 02:00 |
0 9-17 * * 1-5 |
Every hour, 09:00 to 17:00, Monday to Friday |
0 0 * * 0 |
Every Sunday at midnight |
0 0 1 * * |
On the 1st of every month |
0 0 1 1 * |
Once a year, January 1st |
Many systems also accept shortcuts: @hourly, @daily, @weekly, @monthly, and @reboot (run once at startup). They're equivalent to the expressions above; Oh Dear accepts the five-field form.
What about sub-minute schedules? #
By default, crontab only supports running once per minute at most. There's no "every 30 seconds" in the spec.
The usual workarounds are:
- Wrapper scripts that run a command,
sleepa few seconds, and run it again - Long-lived workers (daemons, queue workers) that handle work as it arrives instead of being invoked on a schedule
For Oh Dear's cron monitoring, once per minute is the highest frequency we track.
Using cron expressions in Oh Dear #
When you monitor a scheduled task in Oh Dear, you can specify the frequency in two ways:
- As minutes (for simple intervals like "every 5 minutes")
- As a cron expression (for anything more complex)
Copy the five fields from your crontab, without the command at the end. So for this line:
30 */2 1 1 */2 /usr/local/bin/myscript.sh
...the cron expression is 30 */2 1 1 */2.
That's it. Everything before the command gets pasted into Oh Dear, and we'll alert you whenever the expected execution doesn't come through.
The expression is the easy part #
Across the sites Oh Dear monitors, 23.3% of cron jobs failed or missed a run in the last 30 days (State of Website Uptime). The expression tells your server when to run a job. It says nothing about whether the job actually ran; that's what cron job monitoring is for: silence past the schedule (plus your grace period) becomes an alert.