Linux··4 min

Cron and Scheduled Tasks

cron is the classic Linux task scheduler. It runs commands on a schedule — every minute, every hour, every day, or any combination you define. Understanding the syntax and the gotchas makes it reliable.

cron is the classic Linux task scheduler. It runs commands on a schedule — every minute, every hour, every day, every week, or any combination you define. It has been part of Unix systems for decades and it is still the most widely used tool for scheduled jobs.

How cron works

The cron daemon runs in the background and checks every minute whether any scheduled job should run. Jobs are defined in crontab files — one per user, plus system-wide files.

crontab syntax

Each cron job is one line with six fields:

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

A * means every value for that field.

Examples:

# run every minute
* * * * * /home/jan/scripts/check.sh

# run at 2:30am every day
30 2 * * * /home/jan/scripts/backup.sh

# run at midnight on the 1st of every month
0 0 1 * * /home/jan/scripts/monthly.sh

# run every 15 minutes
*/15 * * * * /home/jan/scripts/monitor.sh

# run at 9am on weekdays only
0 9 * * 1-5 /home/jan/scripts/report.sh

# run at 6am and 6pm
0 6,18 * * * /home/jan/scripts/twice-daily.sh

The */n syntax means every n units. */15 in the minute field means every 15 minutes.

Editing your crontab

crontab -e

This opens your user crontab in your default editor. Each user has their own crontab, and jobs run as that user.

To list your current jobs:

crontab -l

To remove your entire crontab:

crontab -r

Be careful with -r. It deletes everything with no confirmation.

System crontabs

Beyond user crontabs, there are system-wide locations:

  • /etc/crontab — the main system crontab. Has an extra field for the username to run as.
  • /etc/cron.d/ — drop individual crontab files here. Same format as /etc/crontab.
  • /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/ — drop scripts directly into these directories and they run at the corresponding interval.

The /etc/crontab format has an extra username field:

# minute hour dom month dow user command
0 2 * * * root /usr/local/bin/backup.sh

Cron environment

Cron jobs run in a minimal environment — much more minimal than your interactive shell. This causes a lot of confusion.

The PATH in a cron job is usually just /usr/bin:/bin. If your script uses a command that lives elsewhere, cron will not find it.

The safest approach is to use full paths in cron commands:

0 2 * * * /usr/bin/python3 /home/jan/scripts/backup.py

Or set PATH at the top of your crontab:

PATH=/usr/local/bin:/usr/bin:/bin:/home/jan/.local/bin

0 2 * * * backup.py

Capturing output

By default, cron emails output to the local user. On most systems this goes nowhere useful. Redirect output to a log file instead:

0 2 * * * /home/jan/scripts/backup.sh >> /var/log/backup.log 2>&1
  • >> appends stdout to the log file
  • 2>&1 redirects stderr to stdout (so errors also go to the log)

To suppress all output completely:

0 2 * * * /home/jan/scripts/backup.sh > /dev/null 2>&1

anacron

cron assumes the system is always running. If the machine is off when a job should run, that job is skipped.

anacron handles this by tracking when jobs last ran and running missed jobs on the next boot or startup. It is designed for desktops and laptops that are not always on.

anacron is configured in /etc/anacrontab:

# period  delay  job-identifier  command
1         5      daily.jobs      run-parts /etc/cron.daily
7         10     weekly.jobs     run-parts /etc/cron.weekly
  • period — how often to run (in days)
  • delay — how many minutes to wait after startup before running
  • job-identifier — used for tracking when the job last ran
  • command — what to run

anacron is not a replacement for cron. It covers scheduled maintenance tasks on systems that are not always on. cron handles precise time-based scheduling.

Debugging cron jobs

When a cron job does not run as expected:

  1. Check the system log for cron entries: grep cron /var/log/syslog
  2. Make the script executable: chmod +x script.sh
  3. Test the script manually as the cron user: sudo -u jan /path/to/script.sh
  4. Use full paths for all commands inside the script
  5. Log output to a file and check it after the job should have run

cron is straightforward but the environment differences between interactive shells and cron catch almost everyone at least once. Full paths and explicit output redirection solve most problems.

Next up: the firewall — how iptables works and how to manage it with ufw.

0 views