# My cron job didn't run
Source: https://vpsdime.com/knowledgebase/troubleshooting/cron-not-running
Last reviewed: 2026-07-05
Summary: The four reasons cron jobs fail silently, the minimal environment (PATH), the % character gotcha, relative paths, and no output capture, plus how to check whether cron even fired, make failures noisy with MAILTO or logging, prevent overlaps with flock, and when a systemd timer is the better tool.

## What this is

A scheduled job didn't do its thing, or so it seems. Cron fails **silently by design**, so this page does two jobs: find out what happened, and make sure the next failure announces itself. (New to cron entirely? Start with [Scheduling tasks with cron](https://vpsdime.com/knowledgebase/technical-questions/cron-basics), the format, the habits, and the overlap trap, then come back here when something misfires.)

## First: did cron fire it at all?

Check the record instead of guessing:

```
grep CRON /var/log/syslog | tail -20     # Debian/Ubuntu
journalctl -u cron -n 20                 # or crond on RHEL-family
```

- **The job appears at the right time** → cron did its part; the *command* failed. Continue below.
- **It doesn't appear** → the schedule or the crontab itself is the problem: confirm the entry exists under the right user (`crontab -l`, root's and yours are different crontabs), that the cron service runs (`systemctl status cron`), and that the schedule means what you think, paste the five fields into **[crontab.guru](https://crontab.guru/)**, which explains any expression in plain words and catches the classic day-of-week/day-of-month surprises.

## The four silent killers

**1. Cron's environment is nearly empty.** Jobs don't get your shell's environment: `PATH` is typically just `/usr/bin:/bin`, so a command that works at your prompt (`certbot`, `restic`, `node`) dies with "command not found" in cron. Fix: use **absolute paths** (`/usr/bin/certbot`), or set `PATH=` at the top of the crontab.

**2. The `%` character is special.** In a crontab line, unescaped `%` means "newline, and feed the rest to stdin", so a date format like `date +%F` breaks the command in half. Escape every one: `date +\%F`.

**3. Relative paths.** Cron runs from the user's home directory, not your project folder, `./script.sh` and relative config/output paths miss. `cd /path/to/project && ./script.sh`, or absolute paths throughout.

**4. The output went nowhere.** The job may have run and *failed*, and told nobody. Which is the fix that matters most:

## Make failures noisy

Pick one (or both):

- **MAILTO**: put `MAILTO="you@example.com"` at the top of the crontab and cron emails you any output, and failures produce output. (Requires the VPS to [send mail](https://vpsdime.com/knowledgebase/troubleshooting/emails-going-to-spam); also note a job erroring every minute into a local mailbox is [an inode story](https://vpsdime.com/knowledgebase/troubleshooting/out-of-inodes).)
- **Log it**: append `>> /var/log/myjob.log 2>&1` to the entry, `2>&1` is the crucial part, error messages go to stderr, and without it your log shows success while the job fails. For the truly critical (backups!), add a dead-man's-switch ping (healthchecks.io style) so you're alerted when the job *doesn't* run.

## Two upgrades while you're in there

- **Prevent overlaps** on jobs that might outlive their interval: `flock -n /tmp/myjob.lock /path/to/command`, the [cron cascade](https://vpsdime.com/knowledgebase/technical-questions/cron-basics) is one of the classic ways a VPS ends up unresponsive.
- **Consider a systemd timer** for anything important: timers log every run to journald, serialize by design, can catch up on missed runs, and don't have cron's environment quirks. Cron is fine for simple things; timers are the better tool once a job matters, the full recipe is in [Using systemd timers instead of cron jobs](https://vpsdime.com/knowledgebase/technical-questions/systemd-timers). (`@reboot` cron entries in particular are better served by a [real systemd unit](https://vpsdime.com/knowledgebase/troubleshooting/services-not-starting-after-reboot).)

## Still need help?

You can [open a support ticket](https://vpsdime.com/open-ticket/). So we can help on the first reply, it's worth mentioning:

- the VPS hostname or IP,
- the exact crontab line and when you expected it to run,
- what the cron log shows around that time.

## Related questions

- "Why didn't my cron job run?"
- "My script works manually but fails in cron."
- "How do I see cron logs?"
- "What does the % sign do in crontab?"
- "How do I get emailed when a cron job fails?"
- "Cron job or systemd timer, which should I use?"
