What it is
Cron is the scheduler that has been part of Unix since the 1970s. It reads a table of jobs — the crontab — and runs each command when its schedule comes round. That is the whole idea.
What people use it for, in practice: nightly backups, clearing temp files, importing a supplier feed, sending invoice reminders on the first of the month, renewing certificates, and driving WordPress's scheduler properly.
The five fields
┌───────────── minute (0 - 59)
│ ┌─────────── hour (0 - 23)
│ │ ┌───────── day of month (1 - 31)
│ │ │ ┌─────── month (1 - 12)
│ │ │ │ ┌───── day of week (0 - 6, Sunday = 0)
│ │ │ │ │
* * * * * /usr/bin/php /home/user/script.php
Four operators, and that is the entire syntax:
*— every value.* * * * *is every minute.,— a list.0 9,17 * * *is 9am and 5pm.-— a range.0 9-17 * * *is hourly from 9am to 5pm./— a step.*/15 * * * *is every fifteen minutes.
Schedules you will actually use
| Expression | Runs |
|---|---|
*/5 * * * * | Every five minutes |
*/15 * * * * | Every fifteen minutes — the usual WP-Cron replacement |
0 * * * * | Every hour, on the hour |
30 2 * * * | 2:30am daily — the classic backup slot |
0 3 * * 0 | 3am every Sunday |
0 0 1 * * | Midnight on the first of every month |
0 9 * * 1-5 | 9am on weekdays only |
Cron runs in the server's timezone. On our servers that is IST, so 30 2 * * * is 2:30am in India, not UTC. Check with date before you assume.
Setting one up in cPanel
- cPanel → Cron Jobs.
- Put an address in Cron Email. Cron mails you anything the command prints, which is how you find out it has been failing for three weeks.
- Pick a Common Setting, or type the five fields yourself.
- Enter the command with absolute paths:
/usr/local/bin/php /home/username/public_html/cron.php - Add the job, then wait for the first run and check the mail.
To silence a job that works and prints noise, append >/dev/null 2>&1 — but only once you have seen it succeed.
On a VPS
# edit your own crontab
crontab -e
# list what is scheduled
crontab -l
# run as another user
sudo crontab -u www-data -e
System-wide jobs live in /etc/cron.d/ and take an extra field — the user to run as — between the schedule and the command. That difference catches people out constantly.
The four reasons it does not run
1. Relative paths
Cron does not start in your home directory and does not have your shell's PATH. php script.php fails; /usr/local/bin/php /home/user/script.php works. Find the binary with which php and use what it prints.
2. A missing environment
Your interactive shell loads .bashrc; cron does not. Anything that depends on an environment variable needs it set in the crontab itself:
PATH=/usr/local/bin:/usr/bin:/bin
30 2 * * * /home/user/backup.sh
3. The script is not executable
chmod +x /home/user/backup.sh, and make sure the first line is a shebang: #!/bin/bash.
4. An unescaped percent sign
The one nobody guesses. In a crontab, % means a newline. A command containing date +%Y-%m-%d is silently cut off at the first percent. Escape every one as \%.
WordPress: replace WP-Cron
WordPress's scheduler is not cron. It fires when someone loads a page, so on a quiet site scheduled posts do not publish and backups do not run — and on a busy site it fires on every page load, which is its own problem.
Fix both at once. In wp-config.php:
define('DISABLE_WP_CRON', true);
Then add a real cron job every fifteen minutes:
*/15 * * * * /usr/local/bin/php /home/user/public_html/wp-cron.php >/dev/null 2>&1
This is one of the highest-value five-minute changes on a WordPress site, and it is covered in more depth in our WordPress speed guide.
Debugging one that has gone quiet
- Check the cron log —
/var/log/syslogon Debian and Ubuntu,/var/log/cronon AlmaLinux and Rocky. - Redirect output to a file and read it:
>> /home/user/cron.log 2>&1. - Run the exact command by hand first. If it fails interactively, cron was never the problem.
- Test with
* * * * *so you find out in a minute rather than tomorrow, then set the real schedule.
Cron jobs are available on every plan we sell, from shared cPanel upwards. If one will not behave, call +91 75994 50220 and we will look at it with you.