Back to blog

Reference · May 15, 2026

What is a cron job in Linux? A developer's complete reference

Cron runs your script at 3am, every Monday at 9, or every five minutes. This guide covers what it actually is on Linux, how to read and write expressions, where logs go, and when to stop relying on a single server's crontab.
crontap.com / blog
Cron is the time-based job scheduler on every Linux box. How to read expressions, write crontab entries, find logs, fix the five common gotchas, and when to move scheduling off the server.

Cron is the time-based job scheduler that ships with every Linux system. If you have ever wanted a script to run every night at 3am, every Monday at 9, or every 5 minutes during business hours, cron is the thing that runs it. A cron job is one scheduled entry: a command plus a schedule expression. This guide is the developer's complete reference: what cron actually is on Linux, how to read and write a crontab expression, where the logs live, the five most common gotchas, and when local cron stops being enough.

For expression patterns without the Linux context, see the cron syntax cheat sheet and the cron expression recipes hub (every 5 minutes, hourly, weekdays, and more). To verify an expression before you ship it, use the free cron job debugger.

What cron actually is on Linux

The cron daemon (crond) wakes up once a minute, reads the schedule tables, and launches commands whose expressions match the current minute. Schedules live in:

  • Per-user crontabs (crontab -e), stored under /var/spool/cron/crontabs/ (path varies slightly by distro).
  • System crontab /etc/crontab (includes a user column).
  • /etc/cron.d/ drop-in files for packages (same five-field format plus user).

The crontab(5) man page is the authoritative reference for field order and special strings.

Example line that runs a backup script at 2:15am every day:

15 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Reading a cron expression

The five fields

Standard Linux cron uses five fields (minute, hour, day of month, month, day of week):

┌───────── minute        (0 - 59)
│ ┌─────── hour          (0 - 23)
│ │ ┌───── day of month  (1 - 31)
│ │ │ ┌─── month         (1 - 12)
│ │ │ │ ┌─ day of week   (0 - 7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *

* means "any value." */5 * * * * means every 5 minutes. 0 9 * * 1-5 means 9:00am Monday through Friday.

Special characters

SymbolMeaningExample
*Any value* * * * * every minute
,List0,30 * * * * at :00 and :30
-Range0 9-17 * * * hourly 9am-5pm
/Step*/15 * * * * every 15 minutes

Shortcut macros

Many installs support @reboot, @hourly, @daily, @weekly, and @monthly in place of five fields. They are convenient but less portable than numeric fields when you need precise control.

Writing a cron job on Linux

  1. Open your user crontab: crontab -e (uses $EDITOR, usually vim or nano).
  2. Add a line: schedule, then command. Use absolute paths for scripts and interpreters (/usr/bin/python3, not python3).
  3. Save and exit. crontab -l lists what is installed.

Redirect stdout/stderr if you want a paper trail:

0 3 * * * /opt/app/sync.sh >> /var/log/sync.log 2>&1

Mail to the crontab owner is the default when you do not redirect; on busy hosts that becomes spam fast.

Where the logs go

There is no single "cron log" on every distro. Check these in order:

  1. Syslog. grep CRON /var/log/syslog on Debian/Ubuntu, or journalctl -u cron where systemd manages cron.
  2. Your redirect file if you used >> /path/to/log 2>&1.
  3. The application's own logs after cron launches it.

If the job never appears in syslog, cron did not run it (wrong user, syntax error, or daemon not running). If it appears but your script fails, debug the script outside cron first with the same user and environment.

System cron vs user cron

User cron runs as you, with your environment (often minimal: no full shell profile). System cron in /etc/crontab and /etc/cron.d/ runs as root or a service user defined in the file. Package managers drop files into /etc/cron.d/ so updates do not wipe your personal crontab.

Common gotchas

PATH. Cron runs with a tiny PATH, often /usr/bin:/bin. Use full paths or set PATH= at the top of the crontab file.

Environment variables. NODE_ENV, database URLs, and API keys from your shell profile are not loaded. Export them in the crontab or source a small env file from the script.

The trailing newline. Some cron implementations require a newline at the end of the crontab file. A missing final newline can cause the last line to be ignored silently.

Overlapping runs. A job that takes 10 minutes scheduled every 5 minutes stacks up. Use flock or an in-script lock file.

Day-of-week vs day-of-month. When both are restricted, the job runs when either matches (OR semantics), which surprises people who expect AND. Test with tool.crontap.com or croniter in Python.

When local cron is not enough

Linux cron is free and familiar. Production teams outgrow it when:

No retries on transient failure

Cron fires once. A blip 502 from your API leaves the job failed until the next scheduled minute (or day). External schedulers like Crontap retry 5xx responses with backoff and alert when the retry budget is exhausted.

No monitoring or alerts when the job fails silently

Cron emails the crontab owner on non-zero exit codes if mail is configured. Many cloud images disable that path entirely. You want Slack, PagerDuty, or a dead-man check when the job never runs. See Dead man's switch, explained for developers.

Tied to one server's lifecycle

When you redeploy, resize, or replace the VM, crontab dies with the box unless you automate replication. HTTP cron against a stable URL survives deploys and works across regions.

Linux cron is free but single-host. Crontap is $3.25/mo annual flat with retries on 5xx, per-schedule IANA timezones, and failure alerts. Crontap covers 1-minute cadence through weekly, same as Linux cron, without an always-on machine.

Fix this in 60 seconds with Crontap. Free forever tier. Three schedules. No credit card. Schedule your first job →

External cron alternative (Crontap walkthrough)

Expose an HTTP endpoint that runs your job (or triggers it). Lock it down with a shared secret header.

  1. Deploy POST /internal/run-nightly-sync that verifies Authorization: Bearer <token> and runs the sync.
  2. In Crontap, create a schedule pointing at that URL with the header stored in the dashboard (not in crontab).
  3. Set cron 0 2 * * * and timezone America/Chicago per schedule.

Your laptop can sleep. The server can autoscale. The schedule lives in one dashboard across environments.

Platform-specific guides: Python cron jobs, Docker cron jobs, cron jobs for AWS Lambda, WordPress. If yours is not running right now, start with Cron job not running?.

FAQ

How do I run a cron job every 5 minutes?

Expression: */5 * * * *. In crontab: */5 * * * * /path/to/script.sh.

How do I check if my cron job ran?

Check syslog for CRON lines, or your script's log file. grep CRON /var/log/syslog on Ubuntu is the usual first step.

How do I edit cron without root?

crontab -e edits only your user's jobs. You do not need root unless you are changing /etc/crontab or system-wide files in /etc/cron.d/.

What is the difference between crontab and cron?

Cron is the daemon and the scheduling system. Crontab is the per-user table of jobs (the file and the crontab command that edits it).

Can I use cron with Docker?

Yes, but running cron inside a container is brittle. Common patterns: a sidecar cron container, Kubernetes CronJob, or external HTTP cron hitting your service. See planned Docker coverage in the SEO content queue; the external-HTTP pattern is usually the cleanest.

References

Related on Crontap

Fix this in 60 seconds with Crontap. Free forever tier. Three schedules. No credit card. Schedule your first job →

From the blog

Read the blog

Guides, patterns and product updates.

Tutorials on scheduling API calls, webhooks and automations, plus deep dives into cron syntax, timezones and reliability.

Alternatives

Vercel Cron every minute: beating the Hobby hourly limit

Vercel Cron caps Hobby at hourly cadence and 5 jobs, and ties every change to a redeploy. Here is the external cron pattern teams use to ship per-minute schedules, per-IANA timezones, and one dashboard across projects without paying $20/mo per user for Pro.

Alternatives

Cloud Run cron without Cloud Scheduler

Cloud Scheduler costs $0.10 per job per month after the first 3 and asks for OIDC plus IAM bindings on every target. Here is the IAM-free pattern Cloud Run teams use to fire their .run.app URLs on a clock with one bearer token and one dashboard across every GCP project.