1. Capture the output
Cron throws away anything the job prints unless mail is set up on the server, so errors disappear. Add a redirect to the end of the line and run it again:
*/5 * * * * /usr/bin/php /home/site/htdocs/cron.php >> /home/site/cron.log 2>&12>&1 sends error messages to the same file. After the next run, the log usually tells you exactly what is wrong. Make sure the user running the job can write to the log file.
2. Check the schedule means what you think
Paste the five fields into the Cron Expression Builder. Common mistakes:
* 2 * * *runs every minute from 02:00 to 02:59, not once at 2am. Use0 2 * * *.- Setting both a day of the month and a day of the week makes cron run when either matches.
- A schedule like
0 0 31 2 *(31 February) never runs.
3. Check the server's time zone
Cron uses the server's clock, which is often UTC. A job set for 0 9 * * * runs at 9:00 UTC, which may be the middle of the night where you are. Check with:
timedatectl4. Use full paths everywhere
Cron runs with a very short PATH, often just /usr/bin:/bin. Commands like php, node or wp may not be found, and relative file paths are resolved from the user's home folder, not your project. Find the full path with which php and use it, and use full paths for files too. If a script relies on relative paths, change into its folder first:
0 3 * * * cd /home/site/htdocs && /usr/bin/php artisan backup:run >> /home/site/cron.log 2>&15. Load the environment the job needs
Variables you set in your shell profile, such as API keys or a custom PATH, are not loaded by cron. Either set them at the top of the crontab, or load them in a wrapper script. Also check that the PHP version cron uses matches the one your site uses: on servers with several versions installed, /usr/bin/php may not be the one you expect. On CloudPanel, versioned binaries such as /usr/bin/php8.4 make this explicit.
6. Check which user runs it
A job in your personal crontab (crontab -e) runs as you. Jobs in /etc/crontab and /etc/cron.d/ have an extra field naming the user. If the job writes files, it needs permission to write there, and files it creates belong to that user, which can break the website if they are owned by root. On CloudPanel, add cron jobs from the site's Cron Jobs page so they run as the site user.
7. Make sure cron itself is running
systemctl status cron
grep CRON /var/log/syslog | tail -20The second command shows recent runs on Debian and Ubuntu (on newer systems without syslog, use journalctl -u cron). If your job does not appear at all, cron is not reading it: check for typos, and make sure the crontab file ends with a newline. Files in /etc/cron.d/ are skipped if their names contain a dot.
Bonus: jobs that run too long
If a job sometimes takes longer than the gap between runs, two copies can run at once and get in each other's way. flock skips a run while the previous one is still going:
*/5 * * * * /usr/bin/flock -n /tmp/import.lock /usr/bin/php /home/site/import.php >> /home/site/cron.log 2>&1Questions
How do I test a cron job without waiting?
Set it to run every minute (* * * * *), watch the log, then put the real schedule back. To copy cron's sparse environment in your shell, run the command with env -i /bin/sh -c '...'.
Should I use cron or a systemd timer?
Cron is simpler and available everywhere. Systemd timers log every run to the journal and can catch up on runs missed while the server was off. The Cron Expression Builder gives you the timer version of any schedule.