Cron is the Linux task scheduler. It runs scripts on a schedule: every minute, daily, weekly. cPanel has a convenient interface for managing cron without knowing the syntax.
Creating a Cron Job in cPanel
- Log in to cPanel → Advanced → Cron Jobs
- Select a ready-made period (every minute, hour, day) or configure manually
- In the Command field, enter the command or path to the script
- Click Add New Cron Job
Cron Syntax
# minute hour day month weekday command
# Every 5 minutes:
*/5 * * * * /usr/bin/php /home/user/public_html/cron.php
# Every day at 3:00
0 3 * * * /usr/bin/php /home/user/public_html/backup.php
# On Mondays at 9:00
0 9 * * 1 /usr/bin/php /home/user/public_html/report.php
Practical Examples
WordPress: wp-cron
Disable the built-in WP-Cron (it loads the server on every visit) and replace it with a real one:
# Add to wp-config.php:
define('DISABLE_WP_CRON', true);
# Cron job (every 5 minutes):
*/5 * * * * /usr/bin/php /home/user/public_html/wp-cron.php
Daily Log Cleanup
0 2 * * * find /home/user/public_html/logs -name "*.log" -mtime +30 -delete
MySQL Backup
0 4 * * * /usr/bin/mysqldump -u dbuser -ppassword mydb > /home/user/backups/db-$(date +\%Y\%m\%d).sql
/usr/bin/php or /usr/local/bin/php. Find the exact path via cPanel → PHP → PHP Versions.MAILTO=your@email.comMonitoring with an External Service (Dead Man's Switch)
Cron will not tell you that a job stopped running altogether — for example, if the account is temporarily suspended or the server goes down. For critical jobs (database backups, sending reports), add a check through a third-party service such as healthchecks.io or cronitor.io: it waits for an HTTP ping at a set interval and sends an alert if the ping never arrives.
# Append a curl ping after successful completion
0 4 * * * /usr/bin/mysqldump -u dbuser -ppassword mydb > /home/user/backups/db-$(date +\%Y\%m\%d).sql && curl -fsS -m 10 https://hc-ping.com/your-uuid-here
- The ping is sent only on success — if mysqldump fails,
&&stops the chain and the ping is never sent - The service sends an email or a Telegram message if the expected ping does not arrive on time
- This solves the main weakness of cPanel's built-in notifications: they stay silent when a job stops running entirely
Common Cron Errors and What They Mean
| Message in the log or email | What it means |
|---|---|
| /bin/sh: 1: php: not found | The command uses plain php without a full path. Cron runs commands with a minimal PATH and does not see the user's shell aliases |
| Permission denied | The script file is not marked executable, or the job owner lacks permission on the path used in the command |
| The job fired twice, the second half of the command vanished | An unescaped % in the command. Cron treats an unescaped % as a newline and cuts off everything after it |
| No error email arrives even though MAILTO is set | The hosting account blocks outbound mail from the local MTA, or the MAILTO mailbox does not exist |
| mysqldump: Got error: 1045: Access denied | The password in the dump command is stale after the database password was changed in cPanel → MySQL Databases |
When Cron in cPanel Is Not the Right Tool
- You need a task queue with retries and priorities — that requires a persistent worker process (Supervisor, systemd), which is not available on shared hosting
- The job must run more often than once a minute — the minimum interval of standard cron is 60 seconds
- The script sometimes runs longer than the interval between runs — without a lock file, overlapping runs start racing each other
- You need system-level jobs with root privileges (server log rotation, OS package updates) — the account only gives you access to the user's own crontab
- You need a chain of several dependent steps (export, then import, then notify) — cron cannot wait for one job to finish before starting another, aside from crudely chaining commands with
&&on one line
Verifying the Result
After adding a job, do not assume that "no visible error means it worked". Check the result explicitly; for tracking down stuck or failing jobs it helps to cross-check with the articles on diagnosing error_log in cPanel and on automatic backups.
# List the current user's active jobs
crontab -l
# Make sure the backup file was actually created and is not empty
ls -lh /home/user/backups/
# A 0-byte file almost always means
# mysqldump failed with an access error or ran out of disk space