# Scheduled Jobs: cron

cron runs commands at the times you set, even when you aren't at the keyboard: each line of your crontab has five time fields, minute, hour, day of the month, month and day of the week, then the command; crontab -e edits it, crontab -l shows it, and a job's output goes into a log file you name.

Journeyman · Unix · Linux · Updated November 10, 2026

## After this lesson you can

- Read and write the five time fields of a crontab line, such as 30 9 \* \* 1-5 or 0 18 \* \* \*
- Add, list and check scheduled jobs with crontab -e and crontab -l, and send a job's output to a log file

## Key takeaways

- cron is a program that runs in the background and checks every minute whether a line of a crontab, a timetable of jobs, is due.
- A crontab line is five time fields, then a command: 30 9 * * 1-5 reads "at 9:30, every day, every month, Monday to Friday". A * means every.
- crontab -e edits your crontab, crontab -l shows it, and crontab -r removes the whole thing without asking.
- cron has no screen. Add >> logfile 2>&1 to a job's line, or its output and its errors are lost.
- On a Mac, crontab works the same way; Apple's own scheduler is launchd.

You promised yourself you'd back up your school work every evening. You did it three nights running, then forgot for two weeks, and the laptop died the night before the essay was due. People forget; computers don't. On Linux and on a Mac, **cron** is the part that remembers: tell it "run this at 6 every evening", and it does, whether you're there or not. Administrators use it for nightly backups and cleanups; web developers use it to send a site's daily emails.

Make this chapter's practice folder, a school-work folder to back up (the later lessons use it too):

```bash
mkdir -p ~/terminal-practice/school/{backup,school-work/{english,history,science}}
cd ~/terminal-practice/school
printf 'Why the Town Library Matters\nFirst draft\n' > school-work/english/essay.txt
printf 'Outline: libraries, then and now\n' > school-work/english/old-outline.txt
printf 'Hatchet\nThe Giver\n' > school-work/english/reading-list.txt
printf 'Chapter 4: the river towns\n' > school-work/history/notes.txt
printf 'Plant growth, day 1: 2 cm\n' > school-work/science/lab-report.txt
```

Save this as `backup.sh` in the same folder with nano, then `chmod +x backup.sh`:

```bash
#!/usr/bin/env bash
# backup.sh: copies everything in school-work into backup.
cp -r school-work/* backup/
echo "Backed up school-work."
```

## cron: the computer's alarm clock

cron is a **daemon** (read "demon"): a program that runs in the background, with no window, from the moment the computer starts. Every minute it reads each person's **crontab** (*cron table*, a timetable of jobs) and starts any job that's due. Check that it's running, and look at your crontab:

```bash
systemctl is-active cron
crontab -l
```

```text
active
no crontab for sam
```

No jobs yet. (The computer keeps its own in `/etc/crontab`; your jobs always run as you.) `systemctl` is Linux's; on a Mac, skip that line, and `crontab -l` works the same.

## The five time fields, read aloud

A crontab line is five time fields, then the command. In order: **minute** (0 to 59), **hour** (0 to 23, so 18 is 6 in the evening), **day of the month** (1 to 31), **month** (1 to 12) and **day of the week** (0 to 6, with 0 and 7 both Sunday). A `*` is read "every". The five fields together are called a **cron expression**. Read them from left to right, and swap the first two, the way you'd say a time:

![The crontab line 30 9 * * 1-5 followed by the command, with a label under each part: 30 is the minute, 9 the hour, the first * the day of the month (every day), the second * the month (every month), 1-5 the day of the week (Monday to Friday), and the last part the command. Underneath, the whole line read aloud: at 9:30, every day, every month, Monday to Friday](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/11/d74c1ef42d6d4cfb8b2fedf12adb7688.webp)

| Fields | Read aloud |
|---|---|
| `30 9 * * 1-5` | at 9:30, every day, every month, Monday to Friday |
| `0 18 * * *` | at 18:00, every day, every month, every day of the week |
| `*/15 * * * *` | every 15 minutes, all day, every day |
| `0 8 1 * *` | at 8:00, on the 1st, every month |
| `0 20 * * 0` | at 20:00, every Sunday |

`1-5` is a range, read "1 to 5"; a comma makes a list (`1,15`, "the 1st and the 15th"); `*/15` is read "every 15".

Your evening backup is `0 18 * * *`, followed by the script's full path. Ubuntu's `crontab` can check a file without installing it, with `-n` (read "dry run"). Put the line in a file (inside double quotes, `$HOME` becomes your home folder and the `*`s stay as they are) and check it:

```bash
echo "0 18 * * * $HOME/terminal-practice/school/backup.sh" > my-crontab.txt
cat my-crontab.txt
crontab -n my-crontab.txt
```

```text
0 18 * * * /home/sam/terminal-practice/school/backup.sh
The syntax of the crontab file was successfully checked.
```

Change the 18 to 24 and check again, and it refuses, because midnight is hour 0:

```text
"my-crontab.txt":0: bad hour
errors in crontab file, can't install.
```

Not every `crontab` has `-n`; a Mac's checks your lines when you save them in `crontab -e`.

## Adding a job: crontab -e

This command changes your computer: it installs a job that runs every evening until you remove it.

```bash
crontab -e
```

The first time, Ubuntu asks which editor to use: choose nano. Your crontab opens as a page of `#` comments, which cron ignores. Add your line at the bottom, save with Ctrl+O and Enter, and quit with Ctrl+X; crontab checks the line and installs it, and `crontab -l` shows it. To stop the job, `crontab -e` again and delete the line, or put a `#` in front of it.

Two commands need care: `crontab -r` removes your whole crontab without asking (and `r` is right next to `e`), and `crontab my-crontab.txt` replaces your whole crontab with the file. Before you change anything, keep a copy: `crontab -l > crontab-copy.txt`.

## Where the output goes

At 18:00 there's no terminal for `backup.sh` to print to. cron tries to email the output to you, and most laptops have no mail set up, so it's thrown away, errors included. Send it to a log file instead (*Three Streams: Output, Errors and Input*): `>>` (read "append into") keeps every evening's lines, and `2>&1` (read "errors into the same place") adds the errors:

```text
0 18 * * * /home/sam/terminal-practice/school/backup.sh >> /home/sam/terminal-practice/school/backup.log 2>&1
```

Three more things to know. A `%` in a crontab line means "new line" to cron, so keep commands such as `date +%F` inside the script. cron doesn't make up a missed run: if the laptop is asleep at 18:00, tonight's backup doesn't happen. And in WSL, Ubuntu stops a little while after you close its last window, and cron stops with it.

**On a Mac:** `crontab -e` and the five fields work the same way. Apple's own scheduler is **launchd**, which runs jobs described in small settings files (`.plist` files) in `~/Library/LaunchAgents`; Apple's manual says launchd has taken over cron's work, but cron still works.

## Check yourself

2 questions to try on the lesson page.

## So what

One line in your crontab turns "I must remember to do this every evening" into something the computer does for you, at a time you chose, with a log that says what happened.

## Key terms

- [cron](https://www.ask-codey.com/glossary/cron)
- [Crontab](https://www.ask-codey.com/glossary/crontab)
- [Cron Expression](https://www.ask-codey.com/glossary/cron-expression)
- [Daemon](https://www.ask-codey.com/glossary/daemon)
- [launchd](https://www.ask-codey.com/glossary/launchd)

## Cheat sheets

- [Scheduled Jobs: cron](https://www.ask-codey.com/cheat-sheets/bash-cron-cheat-sheet)

## Related

- [Scripts That Run Without You](https://www.ask-codey.com/lessons/bash-unattended-scripts)
- [Backups That Work: rsync](https://www.ask-codey.com/lessons/bash-rsync)
- [Three Streams: Output, Errors and Input](https://www.ask-codey.com/lessons/bash-streams-and-redirection)

Source: https://www.ask-codey.com/lessons/bash-cron
