ProductPricingAboutContactBlogDACertiva ↗Log inStart free →
Troubleshooting

Cron job not running? How to debug it

A cron job that silently stops is one of the hardest failures to notice. Here's how to work out why it didn't run — and how to be told next time.

There's a particular kind of frustration in a cron job that won't run: it works perfectly when you type the command by hand, then does nothing at the scheduled time. No error, no output, no clue. The script is fine — the problem is almost always the gap between the comfortable environment you run things in and the bare, stripped-down world cron actually lives in. Once you understand that gap, debugging a silent cron job stops being guesswork and becomes a short, reliable checklist.

Check the schedule first

Before you suspect anything clever, suspect the schedule — it's the most common culprit by a wide margin. Paste your cron expression into a parser and confirm it actually means what you think it does; “0 0 * * 0” is weekly on Sunday, not daily, and that single misreading accounts for a surprising number of “it didn't run” reports.

Then check two things people forget. Cron uses the server's timezone, which is often UTC rather than your local time, so a job you expect at 9am may be firing at what you think of as the middle of the night. And confirm the cron service itself is even running — a quick systemctl status cron rules out the embarrassing case where the whole scheduler is stopped.

Paths, permissions and environment

Here's the heart of it: cron does not run with your shell. It runs with a minimal environment that has almost none of the conveniences you take for granted, which is why a script that works flawlessly by hand can do nothing under cron.

The usual offenders are all variations on that theme. The script calls a command that isn't on cron's bare PATH. It uses a relative path that only resolves from your working directory. It isn't marked executable. Or it quietly depends on environment variables set in your .bashrc — database URLs, API keys — that cron never loads. The fixes are equally consistent: use absolute paths everywhere, set PATH explicitly at the top of the script, and source any environment you need rather than assuming it's there.

Read the logs

Stop guessing and let the system tell you what happened. Cron logs to the system log, so check /var/log/syslog or journalctl -u cron to answer the first question: did the job fire at all? That one answer splits the problem cleanly in two.

If there's no log line at the expected time, the issue is upstream — the schedule or the cron service — not your script, so go back to step one. If it did fire but the work didn't happen, the script ran and failed silently. Redirect its own output to a file with >> /path/to/log 2>&1 so the next run captures the actual error instead of throwing it away. That redirect turns an invisible failure into a readable one.

How to know the moment it fails with WatchControl

Even after you've fixed today's problem, there's a deeper one the checklist can't solve: a cron job that has run perfectly for months will eventually fail silently anyway. A server crashes, a deploy changes a path, a disk fills up — and because nothing polls a cron job, nothing tells you. You find out when you need the result that isn't there.

Heartbeat monitoring is the answer to that, and it's the one piece that protects you going forward rather than just explaining the past. Your job pings a unique URL when it finishes successfully; if that ping doesn't arrive on schedule, you're alerted. In WatchControl you create a heartbeat monitor and add a single curl line to the end of your job — no agent, free to start — and from then on a cron job that stops becomes a notification, not a nasty surprise.

FAQ

Frequently asked questions

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

Because cron runs with a minimal environment, not your shell. The script likely relies on a command not on cron's PATH, a relative path, executable permissions, or variables from your .bashrc that cron never loads. Use absolute paths, set PATH in the script, and source any environment explicitly.

How do I check if my cron job ran at all?

Look at the system log with /var/log/syslog or journalctl -u cron. If there's no entry at the expected time, the problem is the schedule or the cron service; if it fired but failed, redirect the job's output to a file with >> /path/log 2>&1 to capture the error.

Why is my cron schedule not firing when I expect?

Two common reasons: the cron expression doesn't mean what you think (for example “0 0 * * 0” is weekly, not daily), or cron is using the server's timezone — often UTC — rather than your local time. Verify both with a cron parser and the server's clock.

How do I get alerted when a cron job stops running?

Use heartbeat monitoring: your job pings a unique URL on success, and you're alerted if the ping doesn't arrive on schedule. It's the only way to catch a silent failure without watching logs, because nothing else polls a background job.

Get alerted when a job is missed

Create a heartbeat monitor and add its check-in URL to your cron job — no credit card.