A cron job that runs fine by hand but never fires on schedule is a classic. It's almost always the environment cron runs in — PATH, paths, or permissions. Here is how to debug it.
Quick answer
A cron job that works by hand but not on schedule is almost always cron's stripped-down environment. Use absolute paths for every command and file, set PATH at the top of the crontab, make the script executable, and redirect output to a log (>> /tmp/job.log 2>&1). Also confirm the cron service is running.
If a job runs perfectly by hand but never fires on schedule, it's almost always that cron runs in a stripped-down environment. These are the usual culprits, most common first:
| Symptom | Cause | Fix |
|---|---|---|
| "command not found" in cron only | Cron has a minimal PATH | Use absolute paths (/usr/bin/php …) |
| Script runs but can't find its files | Cron doesn't run from the script folder | cd into it, or use absolute paths inside |
| Nothing happens at all | Bad crontab syntax or missing final newline | Fix the 5 time fields; end the file with a newline |
| Permission denied | Script not executable / wrong user | chmod +x, and check whose crontab it's in |
| Works sometimes, not always | Wrong timezone or overlapping runs | Check the system TZ; add a lock to avoid overlap |
Is cron even running?
Confirm the cron service is active and check the schedule:
systemctl status cron # or crond on RHEL/Alma
crontab -l # list this user's jobsCause 1: a minimal PATH
Cron runs with a bare environment, so commands that work in your shell (because of your PATH) fail. Use absolute paths for everything:
# bad: php script.php
# good:
0 * * * * /usr/bin/php /home/user/script.phpCause 2: relative paths inside the script
Cron doesn't run from your script's folder. Either cd into it first or use absolute paths inside the script:
0 3 * * * cd /home/user/app && /usr/bin/php backup.phpCause 3: see the actual error — log the output
By default you never see why it failed. Redirect output to a log and read it:
0 3 * * * /usr/bin/php /home/user/backup.php >> /home/user/cron.log 2>&1A classic gotcha: a crontab file must end with a newline, or the last job silently won't run. Also remember % must be escaped as \% in cron commands.
Works by hand, not in cron = environment. Use absolute paths, log the output with >> log 2>&1, and read why it failed.
Cause 4: wrong crontab syntax or schedule
A malformed schedule (six fields instead of five, or an invalid range) makes cron silently ignore that line. Validate the schedule syntax against the man page or an online cron expression checker before assuming something else is wrong.
Cause 5: file or script permissions
If the script isn't executable, or the user cron runs as can't read/write files it touches, the job fails silently unless you're logging output. Confirm permissions with ls -l and that the crontab's user actually owns or can access the files — see permission denied on Linux.
Cause 6: wrong crontab (user vs system vs root)
A job added with crontab -e as one user won't run for another. Make sure you're editing the crontab for the user you expect, or use /etc/cron.d/ for system-wide jobs, which need an extra username field.
How to prevent cron issues
- Always use absolute paths for commands and files.
- Always redirect output to a log.
- Test the exact command manually as the cron user, not your own login.
- Keep a monitoring/alert — even a simple heartbeat ping — on critical jobs like backups.
Related errors
If the job runs but a command inside it fails with a permissions error, see permission denied on Linux. For checking what resources a scheduled job is using, see checking CPU/RAM/disk usage. New to the shell? Start with essential Linux commands.