Your Cron Job Is Running But Nothing Is Happening: The Complete Debug Guide
π― Key Takeaways
- Why Your Cron Job Seems to Be Running But Isn't
- The Number One Cause: The PATH Problem
- Cron's Different Environment: More Than Just PATH
- How to Check If Cron Is Even Running the Job
- The Silent Failure Problem: Capturing Output
π Table of Contents
- Why Your Cron Job Seems to Be Running But Isn't
- The Number One Cause: The PATH Problem
- Cron's Different Environment: More Than Just PATH
- How to Check If Cron Is Even Running the Job
- The Silent Failure Problem: Capturing Output
- Common Crontab Syntax Mistakes
- User Crontab vs System Crontab
- Permission Issues
- How to Test a Cron Job Without Waiting
- The Complete Cron Debugging Workflow
Why Your Cron Job Seems to Be Running But Isn’t
You set up a cron job. The cron syntax checker says it is valid. The scheduled time comes and goes. Nothing happens. Or worse β cron runs the job, but the job silently does nothing and you have no idea why. This is one of the most common frustrations for Linux beginners and even intermediate administrators, and it almost always comes down to a handful of predictable causes that are easy to fix once you know what to look for.
π Table of Contents
- Why Your Cron Job Seems to Be Running But Isn’t
- The Number One Cause: The PATH Problem
- How to Fix the PATH Problem
- Cron’s Different Environment: More Than Just PATH
- The Right Way to Handle Environment Variables in Cron
- How to Check If Cron Is Even Running the Job
- Checking System Logs
- The Silent Failure Problem: Capturing Output
- How to Capture Cron Output to a File
- Common Crontab Syntax Mistakes
- The Missing Newline at the End
- Wrong Minute/Hour Field Order
- The @ Shortcut Misunderstandings
- User Crontab vs System Crontab
- Permission Issues
- How to Test a Cron Job Without Waiting
- The Complete Cron Debugging Workflow
The root of most cron problems is a simple but important truth: cron runs your scripts in a completely different environment than your interactive shell. That difference breaks things in ways that seem mysterious until you understand why.
The Number One Cause: The PATH Problem
When you type a command in your terminal, your shell uses the PATH environment variable to find where that command lives. Your interactive shell typically has a rich PATH including /usr/local/bin, /usr/bin, /bin, /home/youruser/bin, and more.
Cron’s default PATH is extremely minimal β often just /usr/bin:/bin. When your cron job runs a command that lives in /usr/local/bin (like node, python3, pip, or custom scripts), cron cannot find it and silently fails.
How to Fix the PATH Problem
The most reliable fix is to always use absolute paths in your cron jobs. Never write:
*/5 * * * * python3 /home/user/script.py
Instead, find where Python3 actually lives and use that:
which python3
# Output: /usr/bin/python3
*/5 * * * * /usr/bin/python3 /home/user/script.py
Do this for every command in your script β not just the main command, but also any commands called within the script itself. Alternatively, set the PATH explicitly at the top of your crontab:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/5 * * * * python3 /home/user/script.py
Or set it at the top of the script itself:
#!/bin/bash
export PATH=/usr/local/bin:/usr/bin:/bin:$PATH
# rest of your script
Cron’s Different Environment: More Than Just PATH
PATH is the most common culprit, but cron’s stripped-down environment causes other problems too. Your interactive shell loads several configuration files on login: ~/.bashrc, ~/.bash_profile, ~/.profile, and system-wide equivalents. These files set up environment variables that your scripts depend on. Cron loads none of these.
Common environment variables that scripts depend on but cron does not provide:
HOMEβ May be set incorrectly, breaking scripts that use~or relative paths.USERandLOGNAMEβ Missing or different from what your script expects.DISPLAYβ Not set, so any GUI application invoked from cron will fail.- Virtual environment activations β Python virtualenvs, Node version managers (nvm), Ruby version managers (rvm) are not activated.
- Custom environment variables you set in
.bashrcβ Database passwords, API keys, custom configuration paths β all missing.
The Right Way to Handle Environment Variables in Cron
For sensitive values like database passwords, source a dedicated environment file at the top of your script:
#!/bin/bash
source /etc/myapp/environment.conf
# environment.conf contains:
# export DB_PASSWORD="secret"
# export API_KEY="key123"
For Python virtualenvs, activate them explicitly with the full path:
*/30 * * * * /home/user/myproject/venv/bin/python /home/user/myproject/script.py
This bypasses the activation step entirely β you are just using the Python binary directly from the virtualenv, which picks up all the right packages automatically.
How to Check If Cron Is Even Running the Job
Before debugging what the job does when it runs, confirm that cron is actually running it at all. Many beginners spend hours debugging a script that cron never even executes.
Checking System Logs
On modern systemd-based Linux systems:
journalctl -u cron -f
# or
journalctl -u crond -f # on RHEL/CentOS
On traditional syslog systems:
grep CRON /var/log/syslog | tail -50
# or
grep CRON /var/log/cron | tail -50
When cron runs a job, it logs a line like:
Mar 6 14:30:01 hostname CRON[12345]: (username) CMD (/path/to/script.sh)
If you see this line, cron is attempting to run your job. If you do not see it, cron is not running it β which means you have a syntax error in your crontab or a timing issue with your schedule.
The Silent Failure Problem: Capturing Output
By default, if your cron job produces any output (to stdout or stderr), cron tries to email it to you using the local mail system. On most modern servers, there is no local mail delivery configured, so that output just disappears into the void. You never see it. Your job fails, produces an error message, and you see nothing.
This is why cron jobs appear to “run but do nothing” β they are running, they are failing, and they are politely emailing you the error message that nobody ever receives.
How to Capture Cron Output to a File
Redirect both stdout and stderr to a log file:
*/5 * * * * /path/to/script.sh >> /var/log/myjob.log 2>&1
The >> appends stdout to the log file. The 2>&1 redirects stderr to the same place as stdout. Now all output β including error messages β goes to your log file where you can actually read it.
If you want a fresh log file each run instead of appending:
*/5 * * * * /path/to/script.sh > /var/log/myjob.log 2>&1
After the cron job should have run, check the log:
cat /var/log/myjob.log
# or watch it in real-time
tail -f /var/log/myjob.log
You will now see exactly what error your script is producing, which makes debugging straightforward.
Common Crontab Syntax Mistakes
The Missing Newline at the End
This one is notorious. If your crontab does not end with a newline character (a blank line at the very end), some cron implementations silently ignore the last job. Always end your crontab with an empty line. You can verify by editing it with crontab -e and ensuring there is a blank line after your last entry.
Wrong Minute/Hour Field Order
Crontab field order is: minute, hour, day-of-month, month, day-of-week, command. This trips up many beginners. The most common mistake is switching minute and hour:
# WRONG - runs at minute 10 of every hour (not 10am)
10 * * * * /script.sh
# RIGHT - runs at 10:00 AM every day
0 10 * * * /script.sh
# RIGHT - runs at 10 minutes past every hour
10 * * * * /script.sh
Use an online cron expression validator or the cronitor tool to confirm your schedule means what you think it means. A helpful way to remember the order: “Minutes Hours Days Months Weekdays β My Hard Drive Makes Whirring noises.”
The @ Shortcut Misunderstandings
Cron supports special @ shortcuts that beginners sometimes misuse:
@reboot # Run once at startup
@hourly # Same as 0 * * * *
@daily # Same as 0 0 * * *
@weekly # Same as 0 0 * * 0 (Sunday)
@monthly # Same as 0 0 1 * *
These are convenient but @reboot in particular can be tricky β it runs when crond starts, not necessarily when the system boots, and it runs before networking is fully available on some systems.
User Crontab vs System Crontab
There are two different types of crontabs and they behave differently:
User crontabs (edited with crontab -e) run as that user. The format has 5 time fields then the command:
*/5 * * * * /path/to/script.sh
System crontabs (files in /etc/cron.d/ or /etc/crontab) have 6 fields β the extra field specifies which user to run as:
*/5 * * * * www-data /path/to/script.sh
If you copy a job from a user crontab to a system crontab file without adding the user field, cron will silently fail or try to run the command as root with your path as the command name. This is a common source of confusion.
Permission Issues
Your script must be executable by the user cron runs it as. Check and fix permissions:
ls -la /path/to/script.sh
# Should show -rwxr-xr-x or similar
chmod +x /path/to/script.sh
Also check that the user running the cron job has read permission on all files the script accesses and write permission on any directories it needs to write to. A script that works perfectly as your interactive user might fail as www-data or another service user with fewer permissions.
How to Test a Cron Job Without Waiting
Waiting 30 minutes for a cron job to run so you can test your fix is painful. Instead, test by manually replicating the cron environment and running the script directly.
The most accurate test is to simulate cron’s environment:
env -i HOME=/root SHELL=/bin/sh PATH=/usr/bin:/bin /bin/sh -c '/path/to/script.sh' >> /tmp/test_output.log 2>&1
cat /tmp/test_output.log
The env -i clears all environment variables, leaving only what you explicitly specify β mimicking cron’s minimal environment. If your script fails in this test, you have confirmed it is an environment problem. If it succeeds in this test but fails in cron, there is something else in the cron environment causing the issue, and you can narrow it down.
The Complete Cron Debugging Workflow
- Add output redirection to your crontab entry:
command >> /tmp/cron_debug.log 2>&1 - Check cron daemon logs to confirm cron is actually executing the job:
journalctl -u cron | grep your_script - If cron runs it but it fails, read
/tmp/cron_debug.logfor the actual error message. - If the error mentions “command not found”, you have a PATH problem. Use absolute paths.
- If the error mentions permissions, check file permissions and the running user.
- Test the script in a simulated cron environment using
env -ias shown above. - Add
set -xto your script for verbose execution tracing during debugging:#!/bin/bash
set -x
# rest of script - Once working, remove debug logging or move it to a proper log file with rotation.
Cron failures almost always have a clear, findable cause. The challenge is that cron hides them by default. Once you add output redirection and know where to look for logs, what seemed like a mysterious black box becomes a straightforward debugging exercise.
”
},
Was this article helpful?
About Ramesh Sundararamaiah
Red Hat Certified Architect
Expert in Linux system administration, DevOps automation, and cloud infrastructure. Specializing in Red Hat Enterprise Linux, CentOS, Ubuntu, Docker, Ansible, and enterprise IT solutions.