All posts

Cron Job Is Not Working? A Fast Diagnostic Checklist

September 3, 2026

When a cron job is not working, the cause is almost always one of six things: the daemon isn't running, the schedule syntax is broken, the environment differs from your login shell, a path or permission is wrong, the job never got to the log, or something less common like a full disk or MAILTO swallowing output. Work through them in that order and you'll usually have an answer fast.

This is a triage guide, not a theory lecture. Scan the checklist, jump to the section that matches your symptom, fix it, then read the last section so this doesn't happen again next month.

Start Here: The 60-Second Triage

Run through this cron troubleshooting checklist before doing anything else:

  1. Is the cron daemon running at all? If it's dead, nothing else matters.
  2. Is the job actually listed? Run crontab -l and confirm the line exists, unedited, under the right user.
  3. Did cron even try to run it? Check the logs for a launch entry at the expected time.
  4. Does the script work when run manually but not under cron? That's an environment problem, not a script problem.
  5. Are file paths and permissions absolute and executable? Relative paths and missing execute bits fail silently.
  6. Is output going anywhere? No redirection means no evidence when something breaks.

If you already know which of these applies, jump to that section. If not, go in order — it mirrors how often each cause actually occurs in practice.

Is the Cron Daemon Actually Running?

Before checking syntax or scripts, confirm the cron daemon not running isn't the actual problem. On most Linux distributions:

systemctl status cron

(On RHEL/CentOS systems, the service is often named crond instead of cron.) You want to see active (running). If it's stopped, crashed, or masked, start it:

sudo systemctl start cron
sudo systemctl enable cron

The enable step matters — it survives reboots, and a job that "used to work but silently stopped" after a server restart is frequently just a daemon that never came back up. If the service won't start at all, check journalctl -u cron for the reason before moving on.

Check the Crontab Syntax and Schedule

With the daemon confirmed alive, inspect the job itself with:

crontab -l

A single misplaced character causes a cron schedule wrong problem that produces zero errors — cron just never fires. Common culprits: six fields instead of five, a stray comma, day-of-week and day-of-month combined incorrectly, or — easy to miss — no trailing newline at the end of the crontab file. Some cron implementations silently ignore the last line if it isn't newline-terminated, which looks exactly like "the job just doesn't run."

Paste your schedule into a cron expression validator if you're unsure, and double-check you're editing the crontab for the correct user — crontab -l as yourself won't show a job installed under www-data or root.

It Works Manually But Not Under Cron: The Environment Problem

This is the single most common real-world cause, and the question behind "cron job not running but works manually." Cron doesn't load your .bashrc, .profile, or login shell. It runs with a minimal environment and a stripped-down PATH — often just /usr/bin:/bin. If your script calls python, node, php, or a custom binary by name rather than full path, cron may not find it at all.

Reproduce cron's exact conditions instead of guessing:

env -i /bin/sh -c '/path/to/your/script.sh'

env -i strips your environment down close to what cron provides. If the script fails here but works in your normal shell, you've confirmed a cron PATH environment variable issue. Fix it by using absolute paths to interpreters and binaries, or by explicitly setting PATH at the top of the crontab itself.

Language runtimes add their own wrinkles. If you're scheduling PHP, see Crontab PHP: The Correct Syntax and Why Jobs Fail Silently for common syntax and environment traps. For Node-based jobs, Cron Jobs in Node.js: Libraries, Pitfalls & Monitoring covers the specific pitfalls of scheduling Node scripts outside an interactive shell.

Permissions, Working Directory, and Relative Paths

Three more silent killers live here. First, a cron job permission denied failure: the script must have its execute bit set (chmod +x script.sh), and cron must be allowed to run as that user at all — check /etc/cron.allow and /etc/cron.deny if jobs mysteriously never run for a particular account.

Second, cron's working directory is typically the user's home directory, not the directory your script lives in. A script that references ./config.json or output.log relatively will look in the wrong place and fail quietly. Convert every path — inputs, outputs, log files — to absolute paths, and cd /full/path/to/project && at the start of the cron command if the script depends on its own directory.

If you're running cron-style jobs on macOS, sleep states and sandboxing add extra failure modes not present on Linux — see Cron Job on Mac: Fixing Permissions, Sleep & Silent Failures for that platform's specifics.

Where to Find Cron's Logs (and What "No Errors" Really Means)

The cron log location depends on your distribution: check /var/log/syslog (Debian/Ubuntu), /var/log/cron (RHEL/CentOS), or journalctl -u cron on systemd systems. Grep for CRON and your username to see whether the job launched at the expected time.

Here's the part that trips people up: a clean entry in these logs only proves cron launched your command — it says nothing about whether the script itself succeeded. This is why a cron job no error message situation is so common; cron's job ends the moment it hands off execution. If your script crashes, throws an exception, or exits non-zero after that handoff, cron never sees it unless you capture it yourself:

* * * * * /path/to/script.sh >> /var/log/script.log 2>&1

Redirecting both stdout and stderr turns invisible failures into a readable log, and checking the exit code (echo $? in a wrapper script) tells you definitively whether the run succeeded.

Still Not Working? Deeper Causes to Rule Out

If the daemon, syntax, environment, paths, and logs all check out, work through this shorter list:

  • MAILTO set to an unmonitored or invalid address can swallow error output that would otherwise reach you.
  • Duplicate cron jobs overlapping — a long-running job triggered every minute can pile up instances that starve each other of resources.
  • Cron job disk full — scripts that write logs or temp files fail outright when the disk fills, often with no obvious message.
  • cron.allow / cron.deny restrictions blocking a specific user from running any jobs.
  • System time or timezone changes shifting when "3am" actually fires.
  • SELinux on RHEL-based systems blocking script execution silently — check audit.log if nothing else explains it.

Stop Finding Out the Hard Way: Monitor the Job

You've likely found and fixed today's issue. The uncomfortable truth is that cron has no built-in way to tell you when it happens again — no failure alert, no missed-run notice, nothing. The exact same silent failure can recur next week, next deploy, or after the next server reboot, and you won't know until someone notices the downstream effect.

The fix is a heartbeat: your job pings a monitoring endpoint on every successful run, and if that ping doesn't arrive on schedule, you get alerted immediately instead of finding out days later. For the full mechanics of catching these failures automatically, read Crontab Monitoring: How to Catch Silent Cron Failures.

Cronevra is built to make that heartbeat setup a five-minute task instead of a project — cron job monitoring with execution history, missed-run detection, and instant alerts, so failures never sit silent again. Check pricing and start monitoring your jobs today.

Frequently Asked Questions

Why does my cron job run manually but not on schedule?

Cron runs with a minimal environment and a stripped PATH, unlike your interactive login shell. Scripts calling interpreters or binaries by name instead of full path often can't be found under cron even though they work fine when you run them directly. Test with env -i /bin/sh -c '/path/to/script.sh' to reproduce cron's conditions exactly.

How do I know if cron even tried to run my job?

Check /var/log/syslog, /var/log/cron, or journalctl -u cron for a CRON entry matching your username and scheduled time. If there's no entry at all, the daemon isn't running or the crontab syntax is preventing the job from ever being scheduled. If there is an entry, cron launched the job — any failure after that point is inside your script.

Why is there no error when my cron job fails?

Cron only reports whether it successfully launched your command, not whether the script itself succeeded. Without explicit output redirection like >> log 2>&1, any crash, exception, or non-zero exit code your script produces simply disappears. Add redirection and exit-code logging to make failures visible.

Can a full disk stop a cron job from running?

Yes — a full disk can prevent a script from writing logs, temp files, or output, causing it to fail outright with no obvious explanation. Check available disk space with df -h when a previously reliable job stops working for no apparent reason.

Do I need to restart cron after editing the crontab?

No. Cron automatically detects changes made through crontab -e and reloads the schedule without a service restart. A restart is only necessary if the daemon itself is stopped, crashed, or was recently reconfigured at the system level.

What's the fastest way to test a script exactly the way cron runs it?

Run env -i /bin/sh -c '/path/to/your/script.sh' to strip your shell environment down close to what cron provides. If the script fails there but succeeds in your normal terminal, the issue is environment or PATH related, not the script's logic.