Troubleshoot cron jobs that do not run as expected
Separate scheduling failures from environment, permissions, output, and application failures with a repeatable diagnostic sequence.
Start by distinguishing three cases: cron never launched the job, cron launched a command that failed, or the job ran but you cannot find its output. Each needs different evidence. A missing email or log line is not enough to decide which occurred.
Confirm the daemon and the schedule
On a systemd-based Debian or Ubuntu host:
systemctl status cron
journalctl -u cron --since today
crontab -l
RHEL-family systems commonly use crond instead. Containers and minimal systems may have no cron daemon or systemd at all. Start and enable the correct service only if this host is intended to own the schedule.
Check the intended user's table, /etc/crontab, and relevant /etc/cron.d/ files. Verify time fields, timezone, final newline and file permissions. User crontabs do not have a username column; system cron files do. Cron's launch log is evidence that a command was scheduled, not proof of successful completion. Logging configuration can also explain missing launch records.
Reproduce the job's execution context
A command that works in your interactive terminal may depend on your account, current directory, shell initialization or credentials. Run a safe test as the actual job user and explicitly choose the working directory and executable paths.
For a script, make its dependencies visible:
#!/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin
export PATH
cd /srv/app || exit 1
exec /srv/app/venv/bin/python /srv/app/jobs/collect.py
Cron supplies a limited environment, not an empty one. It generally does not load your interactive shell profile. If you need to inspect environment differences, record only specific harmless variables such as PATH, HOME and SHELL; dumping the entire environment can expose credentials.
Check permissions and script format
The account needs permission to traverse directories, read inputs, execute the script or interpreter, and write output. Verify the shebang and Unix line endings. A noexec mount, SELinux policy, network filesystem behavior or an unavailable credential can matter even when ordinary mode bits look correct.
Use absolute paths and a deliberate working directory. Do not assume cron starts in the script's directory. In a crontab command, unescaped % has special handling even inside shell quotes; move date formatting into a script or escape it as \%.
Capture the actual result
*/10 * * * * /srv/app/bin/collect.sh >> /var/log/app/collect.log 2>&1
Provision that log for the job account. If the shell cannot open it, the command may never start. Add start, finish, run identifier and exit status to application logs. A job can fail silently, or write warnings and still succeed; use the exit code and the job's business result together.
With Guance log collection, compare local records with ingested records before interpreting a missing event as a missed job. Collection delay or failure is another possibility.
Investigate jobs that start but do not finish
Look for lock contention, resource limits, unavailable dependencies, OOM termination, long network waits and overlapping instances. Cron normally starts the next scheduled instance even if the previous one is still running. Add locking or a timeout only after deciding whether the desired policy is to skip, queue, retry or terminate work.
Common questions
It runs manually; is cron broken? Compare the actual account, environment, working directory and permissions before reaching that conclusion.
Why is there no email? Cron mail depends on output and a configured mail transport. A silent failure can produce none.
Should I restart cron? Normal schedule edits are detected automatically. Restarting does not correct script errors or missing dependencies.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan