Home/Infrastructure/crontab Not Running? 7 Causes When Cron Jobs Fail and a 5-Minute Diagnosis
Infrastructure

crontab Not Running? 7 Causes When Cron Jobs Fail and a 5-Minute Diagnosis

Registered a crontab but cron isn't running? This Linux cron troubleshooting guide walks through 7 causes—daemon, logs, PATH, permissions, syntax, and more—with copy-paste diagnostic commands and a 5-minute checklist to fix it fast.

crontab Not Running? 7 Causes When Cron Jobs Fail and a 5-Minute Diagnosis
Contents
  1. First Things First: Check the Cron Daemon and Logs
  2. Environment Issues That Prevent Execution Entirely
  3. Syntax and Permission Issues: Registered but Ignored or Broken
  4. Conclusion: The 5-Minute Diagnosis Checklist When It Won't Run
  5. Frequently Asked Questions (FAQ)

crontab Not Running? 7 Causes When Cron Jobs Fail and a 5-Minute Diagnosis

You registered it with crontab -e, the syntax looks correct, but nothing happens when the scheduled time passes. What's even more frustrating is that the script runs perfectly when you execute it directly in the terminal. If you landed on this article, that's almost certainly your situation.

The nastiest thing about cron is that it fails silently. It doesn't print errors to the screen, and unless you capture output separately, you won't even know what happened. So debugging should start not with guessing, but with making logs visible. This article walks through symptoms → causes → fixes, with copy-paste commands, so you can narrow down the cause in 5 minutes. (Based on Ubuntu 22.04/24.04 and RHEL 9)

First Things First: Check the Cron Daemon and Logs

Before you blame your code, check whether the cron daemon is even running. If the daemon is dead, no crontab—no matter how perfect—will execute.

Bash
# Ubuntu / Debian
systemctl status cron

# RHEL / CentOS / Rocky / Alma
systemctl status crond

If it's not active (running), start it and enable it to start on boot.

Bash
sudo systemctl enable --now cron     # Ubuntu/Debian
sudo systemctl enable --now crond # RHEL stack

If the daemon is alive, next up are the logs. Cron records that it ran a job. If that record exists, cron did its job and the problem is inside the script. If there's no record at all, cron never even recognized the job.

Bash
# Ubuntu/Debian (syslog )
grep CRON /var/log/syslog

# rsyslog /
journalctl -u cron --since "10 min ago"     # Ubuntu
journalctl -u crond --since "10 min ago"    # RHEL

# RHEL stack dedicated
tail -f /var/log/cron

On Ubuntu 24.04 or minimal installs, rsyslog may be missing, so /var/log/syslog might not exist. In that case, use journalctl to see the logs.

Finally, here's the single most powerful line for making failure causes visible. Append output redirection to the job you're debugging.

CRON
* * * * * /path/to/script.sh >> /tmp/cron.log 2>&1

>> captures stdout, and 2>&1 sends stderr to the same file. A minute later, open cat /tmp/cron.log and you'll see the real cause—command not found, Permission denied, and so on—printed as-is.

Environment Issues That Prevent Execution Entirely

If the job shows up in the logs but there's no result, it's usually because cron's execution environment differs from your terminal.

Causes 1 & 2: PATH Environment Variable Differences (command not found)

This accounts for 80% of cron troubleshooting. Cron doesn't run in a login shell—it executes jobs in an extremely sparse environment. Check it yourself.

CRON
* * * * * env > /tmp/cronenv.txt

A minute later, cat /tmp/cronenv.txt will look nothing like your usual terminal echo $PATH. Cron's PATH is typically just /usr/bin:/bin, so it can't find commands like node, python3, or docker that live in /usr/local/bin/.

There are two fixes, and I recommend applying both.

CRON
# 1) crontab PATH when
PATH=/usr/local/bin:/usr/bin:/bin

# 2) path (which python3 check)
* * * * * /usr/bin/python3 /home/app/job.py >> /tmp/cron.log 2>&1

Confirm the actual path with which python3 and hard-code the absolute path—that's the most reliable approach.

Cause 5: Confusing User crontab with /etc/crontab

The user crontab you register with crontab -e and /etc/crontab (the system crontab) have different syntax. The biggest difference is the user column.

TypeHow to registerUser column after time fields
User crontabcrontab -eNone (runs as that user)
System crontab/etc/crontab, /etc/cron.d/*Present (root, etc.)
CRON
# User crontab (crontab -e)
* * * * * /home/app/job.sh

# /etc/crontab — 5 user !
* * * * * root /home/app/job.sh

If you write /etc/crontab without the user column, everything shifts over one field and the line is ignored entirely. Conversely, if you put root in crontab -e, it gets interpreted as a command and breaks.

Syntax and Permission Issues: Registered but Ignored or Broken

Cause 3: Unescaped % Characters

In cron, % is a special character interpreted as a newline. If a date format includes %, everything after it gets truncated and the command breaks.

CRON
# Before (failed) — %Y
* * * * * /usr/bin/backup.sh > /tmp/dump_$(date +%Y%m%d).sql

# After — % when
* * * * * /usr/bin/backup.sh > /tmp/dump_$(date +\%Y\%m\%d).sql

Cause 4: Missing Newline on the Last Line

If the crontab file is missing a newline on the last line, that line is ignored entirely. Suspect this if you edited the file directly or appended with echo. Opening it with crontab -e and hitting Enter once at the end is enough to fix it.

Cause 6: Missing Execute Permission or Shebang

Cron only invokes the script. If permissions or the interpreter declaration are missing, it simply fails.

Bash
# Before: run → Permission denied
-rw-r--r-- 1 app app 320 job.sh

# After
chmod +x /home/app/job.sh

A shebang on the first line of the script is also required.

Bash
#!/bin/bash # ← run
echo " when"

Cause 7: The Trap of Not Redirecting Output

If you don't redirect, errors go nowhere and you loop forever on "why isn't this working?" During debugging, always append >> /tmp/cron.log 2>&1. Among the 7 causes, this is the most common time-waster.

A note from the field — The incident I see most often is "it worked locally with python job.py but cron wouldn't run it." The cause is almost always PATH and the working directory (cwd). Cron runs from the user's home directory, so if the script reads files with relative paths, it can't find them. Just getting in the habit of putting cd /home/app/project at the top of the script prevents half of these issues.

Conclusion: The 5-Minute Diagnosis Checklist When It Won't Run

Follow this order and you'll narrow down the cause.

  1. Is the daemon running? → systemctl status cron (or crond)
  2. Does the job appear in the logs? → journalctl -u cron --since "10 min ago" / grep CRON /var/log/syslog
    • Not appearing → suspect syntax, registration location (crontab -e vs /etc/crontab), or a missing last-line newline
    • Appearing → move on to problems inside the script
  3. Check absolute paths / PATH → compare cron's environment with env > /tmp/cronenv.txt; use absolute paths for commands + PATH= at the top
  4. Permissions and shebang → chmod +x, first line #!/bin/bash
  5. Capture errors with output redirection → append >> /tmp/cron.log 2>&1 and cat /tmp/cron.log

In container or cloud environments, systemd timers or Kubernetes CronJobs are cleaner than cron for logging (journalctl) and status management. On a single Linux server, though, crontab is still the fastest and most common choice. The moment you need retries, failure alerts, and proper logging is when you should move to systemd timers.

Frequently Asked Questions (FAQ)

Q. It works when I run it manually, but not from cron. Why? A. Cron isn't a login shell, so environment variables like PATH are sparse, the working directory is fixed to the user's home, and the default shell may be /bin/sh. Using absolute paths, setting PATH= at the top of the crontab, adding an explicit cd in the script, and including a shebang will fix most cases.

Q. I registered it to run every minute (* * * * *) but it still doesn't run. A. First check the daemon status and logs. If there's no CRON record in the logs at all, the line was likely ignored due to a missing last-line newline, an unescaped %, or a missing user column in /etc/crontab.

Q. What's the difference between the root crontab and a user crontab? A. sudo crontab -e runs as root; crontab -e runs as the current user. File access permissions and environments differ, so if you registered a job that needs privileges in a user crontab, you may get Permission denied. Always check which user you registered it under with crontab -l.

Q. Why don't environment variables from my GUI or SSH session exist in cron? A. Those variables are set in login-shell init files like .bashrc and .profile, which cron does not read. Define the variables you need directly at the top of the crontab, or explicitly load them in the script with source ~/.bashrc.

✦ ✦ ✦
Sources and verification

Sources and checks vary by article. Only articles with a recorded check date, scope and sources below were checked, and only within that scope. For other articles, verify against the current docs for your version before applying anything, and email us about errors. Editorial policy · email us

This article has no recorded human check (date and scope) yet.

Published ·
Topic-related official docs (auto-linked · not per-claim sources)Linux man pages ↗

Comments

Be the first to comment.