How to Fix "Crontab Script Not Running Automatically" in Linux
Quick answer
Your script runs perfectly when you execute it manually, but cron never seems to trigger it at the scheduled time. Cron jobs run in a stripped-down environment...
Your script runs perfectly when you execute it manually, but cron never seems to trigger it at the scheduled time. Cron jobs run in a stripped-down environment with almost none of your interactive shell's setup, which is the source of the vast majority of "works manually but not in cron" problems.
The Problem
You add an entry to your crontab expecting it to run silently in the background, but nothing happens at the scheduled time β no output, no logs, no sign the script ever executed:
$ crontab -l
0 2 * * * backup.sh
Checking the system logs sometimes reveals cron tried to run it but failed:
$ grep CRON /var/log/syslog | tail -5
Aug 7 02:00:01 myserver CRON[2841]: (user) CMD (backup.sh)
Aug 7 02:00:01 myserver CRON[2842]: (user) CMD (backup.sh)
/bin/sh: 1: backup.sh: not found
Why It Happens
Cron runs jobs with a minimal, non-interactive shell environment β no PATH customizations from your .bashrc, no aliases, none of the environment variables an interactive login shell normally has. This mismatch causes most cron failures:
- Relative paths and bare command names.
backup.shworks interactively because your shell'sPATHincludes the current directory or the script's location β cron's defaultPATHis much shorter and usually doesn't. - Missing environment variables. Scripts relying on variables set in
.bashrcor.profile(API keys, custom tool paths,NVM/rbenvshims) don't have them under cron, since cron doesn't source those files. - Wrong working directory. Cron jobs start in the user's home directory by default, not wherever you happen to be when testing manually β relative file references inside the script break as a result.
- Syntax errors in the crontab entry itself β wrong number of fields, invalid day-of-week value, or a stray character that
crontabsilently accepted but cron can't parse correctly. - The cron service isn't running at all on the machine, which is easy to overlook when debugging the script itself instead of the service.
The Fix
Always use absolute paths for both the script and anything it references internally:
0 2 * * * /home/user/scripts/backup.sh
Inside the script itself, avoid relying on the current working directory β reference files with full paths or explicitly cd to the expected directory at the top:
#!/bin/bash
cd /home/user/scripts || exit 1
./do_backup.sh
Redirect output to a log file so you can actually see what happens (or doesn't) instead of debugging blind:
0 2 * * * /home/user/scripts/backup.sh >> /home/user/logs/backup.log 2>&1
Check that log after the scheduled time to see the real error instead of guessing:
cat /home/user/logs/backup.log
If the script depends on environment variables or a custom PATH, set them explicitly at the top of the crontab file rather than assuming cron inherits your shell's setup:
PATH=/usr/local/bin:/usr/bin:/bin
API_KEY=your_key_here
0 2 * * * /home/user/scripts/backup.sh
Confirm the cron service itself is actually running:
systemctl status cron
β cron.service - Regular background program processing daemon
Loaded: loaded
Active: active (running) since Thu 2026-08-07 09:00:12 UTC
If it's not active, start and enable it:
sudo systemctl enable --now cron
Still Not Working?
If everything above checks out but the job still silently doesn't run, verify your crontab syntax field by field β the five time fields are minute, hour, day-of-month, month, and day-of-week, in that exact order, and a common mistake is transposing hour and minute or using an out-of-range value that cron rejects silently on some systems:
# minute hour day-of-month month day-of-week command
0 2 * * * /home/user/scripts/backup.sh
Test the schedule logic separately from the script itself by temporarily setting it to run every minute, confirming the job fires and logs correctly, then restoring your intended schedule once you've confirmed cron itself is invoking the script as expected:
* * * * * /home/user/scripts/backup.sh >> /home/user/logs/backup.log 2>&1