Cron does not choose its own log file. It sends daemon messages to the host's logging system, and journald or rsyslog decides where they are stored. The result depends on the distro, the installed logging services, and any local configuration. This is the path-by-path reference, plus when you should stop reading log files and start using a managed dashboard.
TL;DR by distro:
- Debian 12:
journalctl -u cron.serviceon fresh installs;/var/log/syslogwhen rsyslog is installed. - Ubuntu Server 24.04:
/var/log/syslogandjournalctl -u cron.serviceon default installs. - RHEL / CentOS / Rocky / AlmaLinux:
/var/log/cronwhen standard rsyslog rules are active; Fedora may be journald-only. - Alpine, BusyBox:
/var/log/messageswith syslogd, or stderr whencrondstarts with-d N. - macOS:
log show --predicate 'process == "cron"' --last 1h. - systemd systems:
journalctl -u cron.serviceorjournalctl -u crond.service, depending on the unit name.
If you are mid-incident and the log file is silent, see cron job not running: the 8-step debug checklist. For the full troubleshooting decision tree, see the cron troubleshooting hub.
Debian and Ubuntu
The cron daemon on Debian-family distros logs its actions through the cron syslog facility, but that does not guarantee a /var/log/syslog file. Fresh Debian 12 (Bookworm) installations are journald-first because rsyslog is no longer installed by default:
journalctl -u cron.service --since todayUbuntu Server 24.04 is different. Its live-server manifest includes rsyslog, so a default server install writes cron records into /var/log/syslog:
grep CRON /var/log/syslogFor the most recent matching lines:
grep CRON /var/log/syslog | tail -50An upgraded Debian host may retain rsyslog and /var/log/syslog. Conversely, minimal Ubuntu images and customized servers may omit or reconfigure it. On a systemd host, use the journal command when the text file is absent, and confirm that the installed unit is named cron.service.
What the line looks like
A typical cron line in /var/log/syslog:
May 24 02:00:01 server CRON[12345]: (root) CMD (/usr/bin/python3 /opt/sync.py)The format is timestamp, hostname, process name with PID, then (user) and CMD (command). That is daemon activity, not the command's output. As the Debian cron manpage explains, classic cron mails unredirected stdout and stderr to the crontab owner or MAILTO recipient. If no working mail transport exists, that output may never reach you.
RHEL, CentOS, Rocky Linux, AlmaLinux, Fedora
RHEL 9 documents /var/log/cron for periodically executed tasks when rsyslog is installed and using the standard rules. Rocky Linux, AlmaLinux, and CentOS commonly inherit that layout, but local images can change it. Fedora may rely on journald without creating the file. The RHEL logging guide lists the standard path and notes that the actual files depend on service configuration:
tail -100 /var/log/cronThis is configured in /etc/rsyslog.conf (or /etc/rsyslog.d/) with a line like:
cron.* /var/log/cronWhen the text file exists, logrotate handles it according to /etc/logrotate.conf and /etc/logrotate.d/. Rotation frequency and retention are local policy, so do not assume that four weeks are available. On RHEL 9, systemd starts logrotate with logrotate.timer.
To follow live:
sudo tail -F /var/log/cronjournalctl -u crond.service is the journal equivalent on systemd-based RHEL-family systems when that unit exists.
What the line looks like
May 24 02:00:01 server crond[12345]: (root) CMD (/usr/bin/python3 /opt/sync.py)Same shape as Debian, slightly different process name (crond instead of CRON).
Alpine and BusyBox
Alpine ships busybox crond rather than vixie-cron. Logging behavior depends on whether syslogd is running:
# Check if syslog is running on Alpine
rc-status | grep syslogIf syslog is up, cron logs land in /var/log/messages:
grep crond /var/log/messagesIf syslog is unavailable (common in minimal containers), the default syslog destination has no receiver. Start crond in the foreground and choose an explicit destination. The BusyBox crond options distinguish -d N, which sets the log level and writes to stderr, from -L FILE, which writes to a named file. A common container command is:
CMD ["crond", "-f", "-d", "8"]The -d 8 option writes level-8 logging to stderr; Docker captures it for docker logs <container>. Use -L /path/to/file instead when you intentionally want a file.
For more on cron inside containers, see Docker cron jobs.
macOS
macOS still ships cron, though Apple has pushed launchd as the modern alternative since 10.4. If you are using crontab -e on macOS, the cron daemon is logging through the Unified Logging system. The legacy /var/log/system.log was retired in macOS Sierra; the modern command is:
log show --predicate 'process == "cron"' --last 1hFor live tailing:
log stream --predicate 'process == "cron"'If your job uses any GUI-bound API (AppleScript that talks to the desktop session, anything that wants the user keychain), cron may run but the side effects fail silently. That is a launchd use case, not a cron one.
systemd journals (any distro)
On a systemd-based distro, query the unit that actually owns the installed cron daemon:
journalctl -u cron.service
# or:
journalctl -u crond.serviceDebian and Ubuntu packages normally use cron.service; RHEL-family packages normally use crond.service. A custom cron implementation can use another unit name, so confirm it with systemctl list-unit-files | grep -E 'cron(d)?\.service'. The journalctl documentation explains how -u filters by a systemd unit.
Useful flags:
--since "1 hour ago"to scope to recent events.-fto follow live.-xto include explanatory messages from the unit.--userif you are looking at user-level systemd timers (not classic cron, but adjacent).
systemd timers are a popular alternative to cron on modern Linux. If your team migrated to *.timer units, journalctl -u myjob.timer and journalctl -u myjob.service are where the logs are.
When the cron log is silent
If grep CRON /var/log/syslog (or the distro equivalent) shows nothing at the expected minute, that alone does not prove the daemon skipped the job. The host may use the journal, the unit or tag may differ, rsyslog routing may have changed, or retention may have removed the entry. After checking the right source, investigate these common causes:
- The cron daemon is not running. Check with
systemctl status cron.serviceorsystemctl status crond.service. - The crontab entry is in a different user's crontab, so a username filter hides the launch record.
- The crontab syntax is invalid and the daemon refused to load the file. Validate in the free cron expression debugger.
- The server's clock is wrong. Run
timedatectland verify the timezone matches what you wrote in the crontab.
The full debug walkthrough is in cron job not running: the 8-step checklist.
When the log shows the job ran but nothing happened
The log line shows that cron attempted to start the configured command. It does not prove the command completed successfully. Common silent failures:
- The command exited 0 without doing work. Wrong env vars, missing DB connection string, a feature flag that turned off the code path. Compare manual run env vs cron run env: add
env > /tmp/cron-env.txtto the job and diff. - The command's output was mailed, discarded because no mail transport was available, or redirected to
/dev/null. Remove suppressing redirects during debugging and send output to a destination you can inspect. - Cron used the wrong shell. Default is
/bin/sh, which isdashon Debian/Ubuntu and lacks bashisms. SetSHELL=/bin/bashat the top of the crontab if your script uses bash features.
When you should not be reading cron logs
You are reading cron logs because something failed and you want to know why. That is fine for a one-off incident. If you find yourself in /var/log/cron more than once a month, the structural answer is to stop reading log files and start using a dashboard that tells you which run failed, when, and which HTTP status or transport error occurred.
Crontap run history records status, HTTP status code, duration, response size, error summary, and each retry attempt. It does not store response bodies. You search the dashboard, not grep. Failure email is available on every plan after retries are used up. Slack, Discord, and Telegram notification channels are available on paid plans. The free Starter tier covers 2 combined schedules, uptime monitors, and heartbeats, including up to 1 uptime monitor at daily cadence and 1 heartbeat at hourly cadence or slower. Pro adds 1-minute cadence and scales as you grow.
Keep the next HTTP cron failure in one place. Move the schedule to Crontap for run history, retries, and failure email instead of another syslog search. Schedule your first job
FAQ
Cron log questions
- Where are cron logs stored on Ubuntu 24.04?
- A default Ubuntu Server 24.04 install includes rsyslog, which writes cron records to /var/log/syslog. The same records are available with journalctl -u cron.service; minimal or customized images may omit rsyslog.
- Where are cron logs stored on Debian 12?
- Fresh Debian 12 installs are journald-first because rsyslog is no longer installed by default. Use journalctl -u cron.service. Upgraded systems or hosts with rsyslog installed may also have /var/log/syslog.
- Where are cron logs on RHEL, Rocky, AlmaLinux, CentOS, and Fedora?
- RHEL and compatible Rocky, AlmaLinux, and CentOS systems commonly write cron records to /var/log/cron when the standard rsyslog rules are active. Fedora may rely on journald instead, so use journalctl -u crond.service if that file is absent.
- Why is the cron log file missing or empty?
- The host may use journald without rsyslog, its syslog rules may differ, or your filter may not match the daemon name. Check systemctl status cron.service or crond.service, then inspect the matching journal unit.
- How do I view cron logs live?
- Use journalctl -f -u cron.service on Debian or Ubuntu, or journalctl -f -u crond.service on RHEL-family systems. For text logs, use tail -F /var/log/syslog or tail -F /var/log/cron.
- Do cron logs include job output, errors, and the exit status?
- Daemon logs normally record that cron launched a command, not its full stdout, stderr, or exit status. Classic cron mails command output unless it is redirected; redirect it explicitly or use a wrapper when you need retained output and status.
- How do I filter logs for one cron job or user?
- Use journalctl -u cron.service --since today | grep -F '(deploy) CMD (/opt/jobs/sync.sh)' to match one user and command, replacing the user, path, and unit for your system. For cleaner filtering, pipe job output through logger with a unique tag and query that tag with journalctl -t.
Related on Crontap
- Cron job not running: the 8-step debug checklist. The companion incident-mode walkthrough.
- Cron troubleshooting. The hub that aggregates this post plus the other failure-mode pages.
- Cron job monitoring. The service page: failure alerts, run history, dead-man pairing.
- What is a cron job in Linux?. The pillar reference for crontab setup, syntax, and daemon model.
Make the next missing run come to you. Schedule the HTTP job in Crontap, then use its history and failure email when the endpoint stops responding. Schedule your first job
