Cron job not running: environment, permissions, timezone, and logging checklist
Cron runs with a smaller environment than an interactive shell. Use absolute paths, explicit logs, and explicit timezones to remove ambiguity.
Maintained by Kevin · Ovalk
Scope and prerequisites
Traditional five-field Unix cron/Cronie. Cloud schedulers, systemd timers and Quartz have different syntax and timezone behavior.
Confirm the task owner and scheduler implementation. The env and flock examples below execute the job: use a staging copy or an idempotent approved job, never a billing or deletion task as a casual test.
Common symptoms
- A script works manually but produces no Cron result.
- A task runs at an unexpected time.
- Expected files or notifications never arrive.
1. Confirm the scheduler loaded the task
Check the task is installed for the intended user, the cron service is running, and syntax is valid. Files in /etc/cron.d also require a username field.
crontab -l
systemctl status cron || systemctl status crond
grep -i cron /var/log/syslog | tail -n 302. Remove interactive-shell assumptions
Cron usually has a minimal PATH and does not load profile files. Set the interpreter, command paths, working directory, environment, and stdout/stderr destination explicitly.
State-changing example below — confirm authorization, scope and recovery before executing.
which python3
env -i PATH=/usr/bin:/bin /bin/sh -c "/absolute/path/job.sh"3. Handle timezone and overlap
Host, container, and application scheduler timezones may differ. Record in UTC for multi-region workloads and use a lock for jobs that can outlast their interval.
State-changing example below — confirm authorization, scope and recovery before executing.
date; timedatectl status
flock -n /tmp/your-job.lock /absolute/path/job.shInterpret the evidence
| Observation | What to check next |
|---|---|
| No scheduler log at the expected time | Check enabled service, task owner, syntax and timezone before debugging application code. Log location is distribution-specific. |
| Scheduler starts job; output missing | Inspect exit status, file permissions, working directory, PATH and stderr. Starting a process does not mean business work completed. |
| Duplicate or skipped runs | Compare duration with schedule, locking behavior and daylight-saving transitions. Monthly day 31 does not occur every month. |
Illustrative diagnosis
A hypothetical example to explain the reasoning, not a reported customer incident or a claim of testing on your stack.
A report works from a developer shell but cron reports “config not found”. The shell starts in the project directory; cron starts elsewhere. An absolute interpreter does not fix a relative config path. Set the working directory inside the script, use an absolute config path and capture stderr in an access-controlled, rotated log.
Verify recovery
- Observe at least one genuine scheduled execution as the intended user and verify its business output plus recorded exit status.
- Confirm a deliberately failed staging run produces an alert and that a long run cannot overlap if overlap is forbidden.
Rollback and stopping point
Save the existing crontab and script configuration before editing. Restore only the changed task if a schedule is wrong, and check for already-running instances before rerunning it. Replaying a job can duplicate side effects.
Prevention and long-term repair
- Write start time, finish time, duration, and exit code for every task.
- Alert on critical job failure and missed execution.
- Keep Cron definitions in version control and test syntax.
References and corrections
Use the documentation for your installed version. The references below explain the underlying behavior; commands still need environment-specific validation.
Report a correction to Kevin — include the page URL, version and a redacted reproduction. See our editorial policy.