Linux online course

Schedule Jobs with Cron in Linux

Learn how cron works in Linux, create system and user cron jobs, write reliable schedules, and troubleshoot permissions, logging, timing, and overlapping runs.

Cron is a Linux background scheduling service. It checks configured schedules regularly, typically once per minute, and starts commands whose time fields match the current time. A command started by cron is called a cron job.

Cron is useful for recurring maintenance, cleanup, backups, reports, log-related work, and application scripts. Because cron runs commands non-interactively, a job must not depend on a terminal, aliases, a login shell, or an interactive password prompt. Use explicit paths, verify permissions, define required environment variables, and handle output deliberately.

How Cron Jobs Work

The cron daemon is a long-running background service. It reads system schedules and user crontabs, evaluates their time fields, and launches matching commands under the configured account. A crontab, short for cron table, is either a file or a managed collection of cron schedule entries.

Cron has minute-level granularity. It is appropriate for “run at 02:30” or “run every 15 minutes,” but not for second-accurate timing. For one-time work, consider at; for service-oriented schedules with dependencies and more detailed controls, systemd timers may be a better fit.

System Jobs and User Jobs

A system cron job is machine-wide automation, commonly used for maintenance and often executed as root or another service account. A user cron job belongs to one account and runs with that account's permissions, making it suitable for personal backups or application-specific tasks.

System versus user crontab

Typical location or management: System jobs commonly use /etc/crontab, files in /etc/cron.d/, or distribution-provided hourly, daily, weekly, and monthly directories. User jobs are managed with crontab -e.

Who edits it: System configuration normally requires administrative privileges. A user manages their own crontab; an authorized administrator can use crontab -u user.

Username field: Traditional system entries include an execution user. Per-user crontab entries do not, because cron already knows the owning account.

Typical use: System jobs handle machine-wide maintenance. User jobs handle personal or application-specific automation.

Risk: Root jobs can affect the entire system. Minimize privileged commands and verify every path.

System Cron Configuration

The common system-wide crontab is /etc/crontab. Its entries contain five scheduling fields, a username, and a command. Many distributions also use directories such as /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, and /etc/cron.monthly/, where applicable. These directory conventions vary, so inspect the target system before relying on them.

sudo cat /etc/crontab

Edit package-managed files carefully. Prefer the distribution's supported mechanisms, preserve comments and file ownership, validate syntax, and avoid changing a file that a package expects to manage. The command sudo crontab -e generally edits root's user crontab; it is not the same thing as editing /etc/crontab.

Managing User Crontabs

Use the following commands for the current account:

crontab -e
crontab -l
crontab -r
  • crontab -e opens the current user's crontab in an editor and creates it if necessary.
  • crontab -l lists that user's scheduled jobs.
  • crontab -r removes the entire crontab, including every job. Treat it as a destructive command and confirm before using it.

When supported and authorized, an administrator can manage another account:

sudo crontab -u alice -e
sudo crontab -u alice -l

Always check which account owns a schedule. Editing your own crontab does not create a job for another user.

Cron Entry Structure

Fields are separated by whitespace. The command begins after the time fields and, in a system crontab, the execution-user field; the command occupies the remainder of the line.

Cron schedule field reference

1. Minute: 0-59. The minute within the hour, such as 30.

2. Hour: 0-23. The hour in 24-hour notation.

3. Day of month: 1-31. The calendar day.

4. Month: 1-12. January through December; names may be supported.

5. Day of week: 0-7. On common implementations, both 0 and 7 mean Sunday.

6. User: Present in system crontab entries, such as root; absent from user crontabs.

7. Command: The executable, script, arguments, and redirections to run.

The system form is therefore commonly described as seven parts: five time fields, user, and command. A user crontab has six parts: five time fields and command.

# /etc/crontab: time fields, user, command
0 21 * * * root /usr/bin/rm -f /home/bob/trash/*

# User crontab: time fields, command
30 2 * * * /home/alice/bin/backup.sh >> /home/alice/logs/backup.log 2>&1

Time-Field Syntax

Cron expression operators

Wildcard (*): Matches every permitted value. * * * * * matches every minute.

List (,): Selects specific values. 0 8,12,16 * * * runs at 08:00, 12:00, and 16:00.

Range (-): Selects a contiguous span. * * * * 1-5 selects Monday through Friday on common implementations.

Step (/): Selects recurring intervals. */15 * * * * selects minutes 0, 15, 30, and 45.

Range with step: 1-10/3 selects 1, 4, 7, and 10 in implementations supporting this standard syntax.

Some cron implementations accept names such as JAN for month 1 and MON for weekday 1. Check the local implementation's documentation before depending on names. Lines beginning with # are comments, and blank lines are ignored.

Useful Schedule Examples

Daily system cleanup

0 21 * * * root /usr/bin/rm -f /home/bob/trash/*

This runs at 21:00 every day. The wildcards match every day of the month, month, and weekday. The root field is required in an /etc/crontab-style entry. Verify the absolute path and test the file selection non-destructively before enabling a deletion job.

Daily user backup

30 2 * * * /home/alice/bin/backup.sh >> /home/alice/logs/backup.log 2>&1

This runs at 02:30 under the crontab owner's account. It uses absolute paths and appends both standard output and standard error to a log.

Every 15 minutes

*/15 * * * * /usr/local/bin/check-status

Selected hours on weekdays

0 8,12,16 * * 1-5 /home/alice/bin/report.sh

The list selects three hours, and the range selects weekdays on common cron implementations.

Scheduling Semantics and Timing Pitfalls

A job runs when the current minute matches its schedule fields. If both day-of-month and day-of-week are restricted, many traditional cron implementations use an OR rule: the job runs when either field matches, while the other time fields must also match. Some implementations or replacements may differ. Check the local cron documentation and test an important schedule rather than assuming an AND rule.

  • Timezone: Cron uses the host or daemon timezone unless the implementation and configuration specify otherwise. Check the system timezone when a job fires at an unexpected local time. Network Time Protocol can help keep system clocks accurate; see NTP on Linux.
  • Daylight saving time: A local hour may occur twice or not occur at all. Jobs can therefore run twice or be skipped around a clock change, depending on the cron implementation.
  • Downtime: A conventional cron daemon does not generally replay every missed run after the machine is powered off. Consider anacron or another scheduler for periodic work on systems that are not always running.
  • Overlap: If a job lasts longer than its interval, another instance may start before the first finishes.

Writing Reliable Cron Commands

  • Use absolute paths for executables, scripts, input files, output files, and directories. The command showing the full path of a shell command can help identify executable locations.
  • Cron supplies a limited environment and often a reduced PATH. Set it explicitly when needed:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  • Set application variables explicitly, or call a script that establishes its own environment. Do not rely on shell profiles, aliases, interactive authentication, or a particular working directory.
  • Quote shell-special characters correctly. In many cron implementations, an unescaped percent sign (%) separates command text from standard input; escape it as \% when a literal percent is required.
  • Redirect output instead of letting it disappear:
/home/alice/bin/task.sh >> /home/alice/logs/task.log 2>&1
/home/alice/bin/quiet-task.sh >/dev/null 2>&1
  • Put nontrivial pipelines and error handling in an executable script. Scripts are easier to test, review, version, and log than long crontab lines.
  • Check ownership and permissions on the script, its inputs, working directories, and log destinations. The executing account must be able to access each one.
  • Use a predictable working directory inside the script if relative paths are unavoidable.

Preventing Overlapping Runs

Use a lock when a job must not run concurrently. The following example uses flock with nonblocking mode, so a new invocation exits if another instance already holds the lock:

*/5 * * * * /usr/bin/flock -n /tmp/import.lock /home/alice/bin/import-data.sh >> /home/alice/logs/import.log 2>&1

Measure the job's runtime and review its logs. If it regularly exceeds the interval, increase the interval or redesign the work instead of allowing uncontrolled concurrency.

Monitoring and Troubleshooting

Log locations differ by distribution and logging service. On systemd systems, inspect the service and journal:

systemctl status cron || systemctl status crond
journalctl -u cron || journalctl -u crond

Traditional logging may place cron messages in one or more of these files:

sudo grep -i cron /var/log/syslog /var/log/cron /var/log/messages 2>/dev/null

Common cron diagnostics

Service status: systemctl status cron || systemctl status crond. Confirms whether the daemon is running; service names vary.

Systemd journal: journalctl -u cron || journalctl -u crond. Shows daemon activity on systemd systems.

Traditional logs: Search /var/log/syslog, /var/log/cron, or /var/log/messages when present.

Crontab listing: crontab -l, or sudo crontab -u alice -l. Confirms the intended account has the entry.

Manual execution: Run the exact command as the same user. This separates command, permission, and environment problems from scheduling problems.

Test a schedule directly

Install a temporary job that writes a timestamp every minute:

* * * * * /usr/bin/date >> /tmp/cron-test.log 2>&1

After waiting at least one or two minutes, inspect /tmp/cron-test.log, then remove the test entry. A harmless timestamp test confirms that the intended crontab is being read and the daemon is triggering jobs.

When the command works interactively but not in cron

  • Check the service status and the correct user's crontab.
  • Replace relative paths and bare command names with absolute paths.
  • Define required PATH and application environment variables.
  • Run the command manually as the same account, not as a different administrator.
  • Capture both output streams in a known writable log file.
  • Check the script, input, output, and directory permissions.

Cron may email a job's output to its owner when local mail delivery is configured. MAILTO can select a recipient:

MAILTO=admin@example.com

If mail delivery is not configured or no mail reader is available, do not rely on email as your only diagnostic method; use explicit logs.

Security and Operational Safety

  • Root-owned jobs have system-wide power. Minimize privileged commands and run a task as a less-privileged service account whenever possible.
  • Review destructive commands, wildcard expansion, variables, and paths. First replace deletion with a listing command or use a dry-run option where available.
  • Use explicit ownership and permissions for scripts and output directories. Do not allow an untrusted user to modify a script executed by root.
  • Add logging and useful error handling. For backups and cleanup, consider verification, retention rules, and a recovery plan.
  • Use locks such as flock to prevent simultaneous instances.
  • Some systems support /etc/cron.allow and /etc/cron.deny to control which users may use crontab. Their precedence and availability depend on the installed cron implementation.

Complete Workflow

  1. Write and test the script manually as the intended account.
  2. Use absolute paths, explicit environment settings, permissions checks, logging, and locking where appropriate.
  3. Choose a user crontab for personal or application work, or a system configuration for machine-wide work.
  4. Translate the desired time into five fields and remember that system entries add the execution user.
  5. Edit with crontab -e or the authorized system mechanism rather than casually overwriting managed files.
  6. List the crontab and inspect service and cron logs.
  7. Use a temporary timestamp test if the result is uncertain, then remove that test.