“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.