Skip to content

Crontab syntax basics, and how it differs from WP-Cron

“What does */5 * * * * actually mean?” — anyone setting up a scheduled task on a server has probably stared at that row of asterisks at some point. If you run WordPress, you may already be familiar with inspecting WP-Cron’s internals through WP-CLI, but the actual crontab syntax used by the OS itself is something many people never learn properly. Before you can switch WP-Cron over to a real OS-level cron job, you need to understand that syntax first.

Note: crontab is a scheduling mechanism built into Unix-like systems (Linux, macOS, etc.). The name is short for “cron table” — a configuration file, and the command used to manage it, that lists what to run and when, one line at a time.

The five time fields

Each line in a crontab consists of five time fields followed by the command to run.

minute hour day month weekday command
*      *    *   *     *       command
Field Range Meaning
minute 0-59 Which minute to run at
hour 0-23 Which hour to run at (24-hour clock)
day 1-31 Which day of the month
month 1-12 Which month
weekday 0-7 (0 and 7 both mean Sunday) Which day of the week

* is a wildcard meaning “every value” for that field. A line where all five fields are * runs every single minute.

Common patterns worth memorizing

In practice, a handful of combinations cover almost everything you’ll need.

# Run every minute
* * * * * command

# Run every 5 minutes
*/5 * * * * command

# Run daily at 3:00 AM
0 3 * * * command

# Run at 9:00 AM on weekdays (Mon-Fri)
0 9 * * 1-5 command

# Run at midnight on the 1st of every month
0 0 1 * * command

The slash notation in */5 is called a step value — “starting from 0, every 5 units.” The hyphen in 1-5 is a range, covering Monday(1) through Friday(5). You can also list specific values with commas, like 1,3,5. Once you’re comfortable combining steps, ranges, and comma lists, most schedules become expressible.

Some cron implementations also support shorthand strings like @daily (equivalent to 0 0 * * *) or @hourly (equivalent to 0 * * * *). They read more clearly, but support varies by implementation, so it’s worth treating the five-field syntax as the portable baseline.

Editing with crontab -e

Jobs that run under your own user account are managed with crontab -e.

# Edit the current user's crontab
crontab -e

# List the current user's crontab
crontab -l

# Remove the current user's crontab entirely
crontab -r

crontab -e opens whatever text editor is set in your EDITOR environment variable. Changes take effect as soon as you save — no restart or reload step is needed. Because crontab -r wipes everything at once, it’s worth making a habit of running crontab -l first to confirm what you’re about to delete.

The PATH environment trap

Jobs run by cron execute with a much smaller PATH environment variable than your interactive login shell. A command that works fine when you type it yourself can fail with “command not found” once it’s running from cron — this is one of the most common causes of “it works when I run it manually, but not from cron.”

# Works in a login shell, but may not be found in cron's minimal PATH
0 3 * * * wp cron event run --due-now

# Fix: specify the full path to the binary
0 3 * * * /usr/local/bin/wp cron event run --due-now --path=/var/www/html

# Or set PATH explicitly at the top of the crontab file
PATH=/usr/local/bin:/usr/bin:/bin
0 3 * * * wp cron event run --due-now --path=/var/www/html

Running which wp (or the equivalent for whatever command you’re scheduling) ahead of time and writing the full path into the crontab entry is the most reliable fix.

How this differs fundamentally from WP-Cron

The OS-level crontab covered above and WordPress’s built-in WP-Cron share a name, but they work on completely different principles.

Aspect OS crontab WP-Cron
What triggers execution The OS cron daemon, watching the clock Every page load, when WordPress checks for overdue tasks
Low-traffic periods Still runs on schedule Doesn’t run — the task waits for the next visitor
What actually runs it An OS process, independent of the web server A PHP process, running as part of handling a request
Where the schedule lives Edited via crontab -e Stored in the wp_options table

The reason WP-Cron is often described as “a pseudo-cron that depends on traffic” comes straight from the first row of that table. A scheduled post that doesn’t go live on time on a low-traffic site late at night is a direct symptom of that design constraint.

Switching to a real crontab entry

Adding define('DISABLE_WP_CRON', true); to wp-config.php stops WP-Cron’s automatic page-load trigger. From there, an OS crontab entry that periodically invokes WP-CLI gives you execution that no longer depends on visitor traffic.

# Process any overdue WP-Cron tasks every 5 minutes
*/5 * * * * /usr/local/bin/wp cron event run --due-now --path=/var/www/html/wordpress > /dev/null 2>&1

> /dev/null 2>&1 discards both standard output and standard error. Cron’s default behavior is to try emailing you the output of every job, and on a server without mail configured, that can fail silently and repeatedly — appending this redirect avoids it. If you’d rather keep a record, point it at a log file instead of /dev/null.

Summary

What you want Syntax / command
Run every 5 minutes */5 * * * *
Run at 9 AM on weekdays 0 9 * * 1-5
Edit your crontab crontab -e
List your crontab crontab -l
Avoid PATH issues Use the full path to the command
Discard output Append > /dev/null 2>&1

The five-field crontab syntax itself is simple, but the differences from an interactive shell — a minimal PATH, and cron’s habit of trying to email job output — are where people usually get tripped up. Combined with the WP-CLI commands for inspecting WP-Cron’s internals, this gives you a way to run WordPress’s scheduled tasks through the OS’s own reliable scheduler instead.