Cron is the Unix and Linux time-based job scheduler: a background daemon that wakes up every minute, reads schedule tables called crontabs and starts the commands whose time specification matches the current minute. In Linux process management, cron is the classic way to run recurring, unattended processes such as backups, log rotation, report generation and cleanup tasks.
Each scheduled command runs as a new process owned by the crontab’s user, with its own minimal environment and no terminal. Understanding that execution context explains most of the problems people meet when a script works in a shell but fails when cron starts it.
How the cron daemon schedules jobs
The cron daemon, called crond or cron depending on the distribution, starts at boot and checks its tables once per minute. Common implementations are cronie on Fedora and RHEL-family systems and Vixie cron derivatives on Debian and Ubuntu. The minute is the smallest scheduling unit; cron cannot start jobs at second-level precision.
When an entry matches, the daemon forks a child process, switches to the owner’s user and group, sets a few environment variables and runs the command through /bin/sh. Standard output and error are collected and, by default, mailed to the owner if a local mail system is configured; otherwise the output is discarded or logged, depending on the implementation.
Cron reads tables from several places, which the table below lists.
| Location | Owner | Format |
|---|---|---|
User crontabs edited with crontab -e | Individual users | Five time fields and a command |
| /etc/crontab | System administrator | Five time fields, a user name, a command |
| /etc/cron.d/ | Packages and administrators | Same as /etc/crontab |
| /etc/cron.hourly, daily, weekly, monthly | Packages | Executable scripts, no time fields |
The crontab time format
A crontab entry consists of five time and date fields followed by the command. A job runs when the minute, hour and month fields match and either the day-of-month or the day-of-week field matches, if both are restricted.
| Field | Allowed values | Example |
|---|---|---|
| Minute | 0 to 59 | 30 |
| Hour | 0 to 23 | 2 |
| Day of month | 1 to 31 | 1 |
| Month | 1 to 12 or names | * |
| Day of week | 0 to 7 or names, 0 and 7 mean Sunday | 1-5 |
Fields accept lists, ranges and steps: 1,15 means both values, 1-5 a range and */15 every fifteenth unit. Most implementations also understand shortcuts such as @daily, @hourly and @reboot. The table shows frequent patterns.
| Expression | Meaning |
|---|---|
*/5 * * * * | Every five minutes |
0 * * * * | At the start of every hour |
30 2 * * * | Daily at 02:30 |
0 9 * * 1-5 | At 09:00 on weekdays |
0 0 1 * * | At midnight on the first day of each month |
@reboot | Once after the daemon starts |
Cron compared with other schedulers
Cron is the most widespread scheduler but not the only one. Its closest alternatives differ in how they handle missed runs, dependencies and logging.
| Tool | Schedule type | Missed runs | Strengths |
|---|---|---|---|
| cron | Recurring, minute resolution | Skipped while the system is off | Simple, universal, portable |
| anacron | Daily, weekly, monthly | Run after the system starts | Laptops and machines that power off |
| systemd timers | Calendar or monotonic | Optional catch-up with Persistent=true | Journal logging, dependencies, resource limits |
| at | One-time | Not applicable | Single deferred commands |
| Kubernetes CronJob | Cron syntax in a cluster | Configurable deadline | Containerized jobs on cluster nodes |
Systemd timers start jobs as service units, so they can use cgroup resource limits, nice values and CPU affinity set in the unit, and their output lands in the journal. Cron remains preferable where portability across Unix systems and a single readable line per job matter more.
Execution environment and practical configuration
Cron jobs run with a deliberately small environment: typically HOME, LOGNAME, SHELL=/bin/sh and a short PATH such as /usr/bin:/bin. Shell startup files are not read, and no terminal is attached, so interactive prompts hang or fail.
- Use absolute paths for commands and files, or set
PATHat the top of the crontab. - Redirect output to a log file, for example
>> /var/log/job.log 2>&1, so failures leave evidence. - Set MAILTO to receive output by mail, or to an empty value to suppress mail.
- Prevent overlapping runs with
flock -nwhen a job may take longer than its interval. - Lower priority of heavy jobs with
niceandioniceto protect interactive workloads.
Access can be restricted with cron.allow and cron.deny files. Production teams also keep crontabs in version control or configuration management, because a schedule edited only on one server is easily lost or forgotten.
Common pitfalls
Most cron failures are silent, which makes their causes worth knowing in advance.
- Percent signs: an unescaped
%in a crontab command is turned into a newline; write\%, for example indateformats. - Time zone and daylight saving: jobs between 01:00 and 03:00 may run twice or not at all on transition days in many zones.
- Day-of-month and day-of-week together: restricting both means either condition triggers the job, not both.
- Missing final newline: some implementations ignore the last line of a crontab without a newline.
- Synchronized load: thousands of machines running jobs at minute 0 cause load spikes; a random delay spreads them.
When a job seems not to run, the fastest diagnosis is to check the daemon log first, through the journal or the system log, which records each start. If the job started, the next step is to reproduce its environment with env -i and a short PATH, which usually reveals the missing variable or relative path within minutes.
Explained without jargon
Many computer chores need to happen regularly: saving backups at night, cleaning up old files each week or sending a report every Monday morning. Doing this by hand is tedious and easy to forget.
Cron is an alarm clock for the computer. A person writes a short line saying when a task should run and what it is, and cron starts it at exactly that time, every time. Once a task is scheduled, it runs without anyone being present.
A typical use case
An administrator of a small company’s Linux server needs a nightly database backup that finishes before staff arrive. She writes a backup script and adds the line 30 2 * * * flock -n /run/backup.lock /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1 to the root crontab.
The first night, the log shows that the pg_dump command was not found, because cron’s short PATH did not include its directory. After she sets PATH at the top of the crontab, the backup runs every night at 02:30, the lock prevents overlapping runs when a backup is slow, and the log records every result.
A weekly check of the log file and an alert on missing entries complete the setup, so a failed backup is noticed within a day instead of when a restore is needed.