Linux Cron Jobs

By Vishvesh Patel · DevOps EngineerUpdated September 16, 2026

Schedule jobs with cron. The five fields, why a job that works manually fails in cron, capturing output and errors, and cron vs systemd timers.

What Cron Is

cron is the traditional Linux scheduler for recurring tasks. It runs commands or scripts automatically at specific times, which makes it useful for backups, cleanup jobs, report generation, and health checks.

If you have ever needed something to run every night at 2:00 AM or every five minutes, cron is one of the first tools to learn.

Managing Your Crontab

Each user can have a personal crontab file.

Open it for editing:

crontab -e

List current entries:

crontab -l

Remove the current user crontab:

crontab -r

Be careful with crontab -r because it deletes all scheduled entries for that user.

Tip: Always run crontab -l before making major changes so you know exactly what is already scheduled.

Understanding Cron Syntax

A cron schedule has five time fields followed by the command:

* * * * * /path/to/command

The fields are:

  1. minute
  2. hour
  3. day of month
  4. month
  5. day of week

Examples:

0 2 * * * /opt/scripts/backup.sh
*/5 * * * * /opt/scripts/health-check.sh
30 6 * * 1 /opt/scripts/weekly-report.sh

These mean:

  • 0 2 * * * = every day at 02:00
  • */5 * * * * = every five minutes
  • 30 6 * * 1 = every Monday at 06:30

Common Cron Job Examples

Backup script

Run a backup every night:

0 1 * * * /usr/local/bin/backup-db.sh >> /var/log/backup-db.log 2>&1

This appends both standard output and errors to a log file.

Log cleanup or rotation helper

15 3 * * 0 /usr/local/bin/archive-old-logs.sh

Health check

*/10 * * * * curl -fsS http://localhost:8080/health || echo "health check failed"

A health check job can test an internal endpoint and alert if the result is unexpected.

Note: Cron runs with a limited environment. Commands that work in your interactive shell may fail unless you use full paths or set needed variables explicitly.

System Cron Directories

Not all scheduled jobs live in a user crontab. Linux systems also include system-wide scheduling locations.

/etc/cron.d/

This directory contains cron files managed by packages or administrators. Files here usually include an extra field for the user account that should run the job.

Example entry:

0 4 * * * root /usr/local/bin/system-backup.sh

/etc/cron.daily/, /etc/cron.weekly/, and friends

These directories hold scripts that run on a daily, weekly, or monthly schedule depending on the system configuration.

You may see:

  • /etc/cron.hourly/
  • /etc/cron.daily/
  • /etc/cron.weekly/
  • /etc/cron.monthly/

Dropping a script into the right directory can be simpler than writing a full cron expression for routine maintenance tasks.

Good Practices for Cron Jobs

When writing cron jobs:

  • use absolute paths such as /usr/bin/python3
  • redirect output to logs or monitoring
  • keep scripts idempotent when possible
  • test the script manually before scheduling it
  • make sure the script has execute permission

A script that depends on your interactive PATH, aliases, or current directory is likely to break under cron.

systemd Timers as a Modern Alternative

Many modern Linux systems use systemd timers as a more structured alternative to cron. Timers pair with systemd service units and often provide clearer logging, dependency handling, and status inspection.

A timer based workflow might look like this:

systemctl list-timers
sudo systemctl enable --now backup.timer
journalctl -u backup.service

Cron is still widely used and worth learning, but systemd timers are often preferred for services that already live in the systemd ecosystem.

A Practical Troubleshooting Flow

If a cron job did not run, check:

  • whether the schedule is correct
  • whether the script path is absolute
  • whether the command works manually
  • whether output was redirected somewhere useful
  • whether the cron service is running on that host

A job that silently fails is often missing environment variables, permissions, or full command paths.

What You Should Remember

Cron is a lightweight and powerful scheduler built around time expressions and shell commands. Use crontab -e to edit, crontab -l to inspect, and system cron directories for broader maintenance tasks.

For modern service-based workflows, systemd timers can offer better observability, but cron remains a core Linux skill.

Test Your Understanding

Exercise

Exercise 1: Reading a cron expression

What does the schedule `*/5 * * * *` mean?

Exercise

Exercise 2: Editing scheduled tasks

Which command opens the current user's crontab for editing?

Exercise

Exercise 3: Limited cron environment

Why do many cron jobs use absolute command paths like `/usr/bin/python3`?


Frequently Asked Questions

How do I read cron syntax?

Five fields: minute, hour, day of month, month, day of week. Then the command. 0 3 * * * is 03:00 every day; */15 * * * * is every fifteen minutes; 0 9 * * 1-5 is 09:00 on weekdays. The trap is that day-of-month and day-of-week are OR'd, not AND'd, so 0 0 1 * 1 runs on the 1st and every Monday. Use crontab -l to review and a site such as crontab.guru to check an expression before trusting it.

Why does my cron job work manually but not from cron?

Almost always PATH. Cron runs with a minimal environment, typically just /usr/bin:/bin, so a command that resolves in your interactive shell is not found by cron, and your shell's profile is never sourced. Use absolute paths for everything (/usr/bin/python3 /opt/app/job.py), or set PATH= at the top of the crontab. The second most common cause is a relative path in the script itself, since cron starts in the user's home directory rather than where the script lives.

How do I see cron job output and errors?

By default cron emails output to the account's local mailbox, which on most servers nobody reads. Redirect it explicitly instead: 0 3 * * * /opt/backup.sh >> /var/log/backup.log 2>&1. The 2>&1 is essential, without it you capture normal output and lose the error messages, which are exactly what you need. To confirm cron even ran, check journalctl -u cron on Debian and Ubuntu or journalctl -u crond on RHEL-family systems, or /var/log/syslog.

What is the difference between crontab -e and /etc/crontab?

crontab -e edits the current user's personal crontab, stored under /var/spool/cron, and its entries run as that user with five time fields. /etc/crontab and files in /etc/cron.d/ are system-wide and take an extra field for the user to run as. Six fields before the command. Forgetting that extra field is the usual reason an /etc/cron.d entry silently does nothing. Prefer a file in /etc/cron.d/ for anything managed by configuration management, since it can be deployed as a file.

Should I use cron or a systemd timer?

Cron for simple, portable, recurring jobs. It is universally available and a one-line entry. systemd timers for anything that needs more: journalctl integration for logs, Persistent=true to run a missed job after downtime, dependency ordering, resource limits, and randomised delays to avoid thundering herds. Timers need two files rather than one line, which is the main cost. In containers, neither may be present. Most base images run no cron daemon at all, so scheduling belongs outside the container.

*What does /5 mean in a cron expression?

A step value: "every 5" within that field. In the minute position, */5 * * * * runs at minute 0, 5, 10 and so on. In the hour position, 0 */6 * * * runs at 00:00, 06:00, 12:00 and 18:00. Steps are not modulo arithmetic across boundaries, so */7 in the minute field fires at 0, 7, …, 56 and then again at 0. A 4-minute gap at the top of each hour. For intervals that do not divide 60, list the values explicitly.

Continue Learning

Explore Related Topics

Try the Tool

Practise this in the browser

Linux Playground

Practise real shell commands in a simulated terminal.

When it breaks

Related Resources