Linux Cron & Task Scheduling

Cron syntax, user vs system crontabs, /etc/cron.d vs /etc/crontab, environment pitfalls, systemd timers as the modern alternative, and debugging strategies. Essential for any infrastructure or backend role.

Overview

What cron is

Cron is the Unix daemon for scheduled command execution. The modern cron daemon on most Linux distributions is vixie-cron or cronie, and the syntax has been stable for decades.

Where cron matters in DevOps

  • Periodic server maintenance — Backups, log rotation, report generation
  • Scheduled CI pipelines — GitHub Actions schedule:, Jenkins "Build periodically" and Kubernetes CronJobs all use the same five-field syntax
  • "Why didn't my job run" incidents — Almost always environment differences or time zone confusion

Three gotchas behind 80% of cron incidents

  • Environment — PATH is typically /usr/bin:/bin, HOME is the user's home, SHELL defaults to /bin/sh. Scripts relying on a rich PATH, NVM, conda or bash syntax silently fail — Absolute paths for every executable, or PATH= at the top of the crontab
  • Output — Cron mails stdout+stderr to the crontab owner via the local MTA; most servers have no MTA, so output is discarded — Add >> /var/log/myjob.log 2>&1 to every command
  • The user — User crontabs (crontab -e, no user column) vs system crontabs (/etc/crontab and /etc/cron.d/*, with an extra user column) — Mixing them causes permission errors that look like the job isn't running

For new systems: systemd timers

> [!TIP] Prefer systemd timers for new infrastructure: full journal logging, Persistent=true for missed fires, resource limits, and integration with the dependency graph. Cron is still ubiquitous and worth understanding deeply.

Key concepts

crontab command
Manage the per-user crontab (stored in /var/spool/cron/crontabs/): User crontab format (no USER column):
/etc/cron.d and system crontabs
System crontabs run commands as a specified user (the extra column): Drop-in files in /etc/cron.d/ must have no extensions and no world-write permission — cron ignores files with wrong permissions silently. Unlike user crontabs, these are managed by package managers or Ansible/Puppet and survive user removal. The /etc/cron.{hourly,daily,weekly,monthly}/ directories are simpler: drop an executable script there and run-parts executes it at the appropriate interval. No schedule expression needed — just the executable bit and correct directory.
Common cron expression patterns
Use crontab.guru to verify expressions interactively. Always think in UTC — cron reads the system timezone unless CRON_TZ is set.
systemd timer units
Two files per scheduled task. The timer activates the matching service. OnCalendar mirrors cron but is more readable: weekly, monthly, Sat *-*-* 04:00:00. OnBootSec=2min fires 2 minutes after boot — better than @reboot with no delay control.
Debugging cron failures
Standard debugging workflow: Common root causes of "cron job doesn't run": — Wrong file permissions on /etc/cron.d/ (world-writable = ignored silently) — Missing executable bit on the script — PATH doesn't include the binary — Script uses bash-isms but SHELL=/bin/sh (fix: add #!/bin/bash shebang, set SHELL=/bin/bash in crontab) — NVM/rbenv/conda active in interactive shell but not in cron (fix: use absolute paths) — Windows line endings (\r\n) in the crontab file — silently breaks parsing (fix: dos2unix)

When to use it

  • Any role involving Linux server administration, infrastructure engineering, or SRE
  • Designing or debugging scheduled jobs: backups, report generation, log rotation, health checks
  • Kubernetes: CronJob resources use the identical five-field cron syntax
  • GitHub Actions: the schedule: trigger uses vixie-cron syntax (UTC timezone always)
  • Jenkins: job scheduler ("Build periodically") and SCM polling use the same five-field format

Interview questions

  • Write a cron expression for: run a backup every weekday at 2:30 AM, and a report every Sunday at 8 AM. What file would you put this in and why?
  • A script runs perfectly when executed manually but fails silently in cron. Walk through your diagnosis.
  • You need to ensure a cleanup job on a fleet of 50 servers doesn't hammer a shared database all at once. How do you implement the schedule?
  • Compare cron and systemd timers — when would you choose one over the other?
  • How do Kubernetes CronJobs differ from Linux cron, and what are the key pitfalls?

Sign up free to read the full topic

More DevOps topics

Start free on Cariara · Coding problems · System design studio