# crontab — Schedule Recurring Commands with the cron Daemon

> Practical guide to crontab — schedule recurring jobs with cron, master the five-field syntax, logging and environment, and avoid the crontab -r trap.

Source: https://www.jpkc.com/db/en/cheatsheets/shell-system/crontab/

<!-- PROSE:intro -->
crontab is the classic job scheduler on Unix and Linux: you store commands alongside five time fields, and the cron daemon runs them reliably in the background – from a nightly backup to a health check every five minutes. The tricky part is rarely the schedule, it's the environment: cron starts jobs with a minimal `PATH` and without your login profile, a literal `%` in a command must be escaped, and `crontab -r` wipes your entire crontab with no confirmation – dangerously close to `crontab -e`. This guide walks you through the commands, the syntax and the pitfalls.
<!-- PROSE:intro:end -->

## Managing Crontabs

`crontab -e` — Edit the current user's crontab file in the default editor.

```bash
crontab -e
```

`crontab -l` — List (display) the current user's crontab entries.

```bash
crontab -l
```

`crontab -r` — Remove (delete) the current user's entire crontab. Warning: no confirmation and easily confused with `crontab -e` – back it up first with `crontab -l > backup.txt`.

```bash
crontab -r
```

`crontab -u <user> -e` — Edit another user's crontab (requires root).

```bash
sudo crontab -u www-data -e
```

`crontab -u <user> -l` — List another user's crontab entries.

```bash
sudo crontab -u deploy -l
```

`crontab <file>` — Install a crontab from a file (replaces existing crontab).

```bash
crontab mycron.txt
```

`crontab -l > <file>` — Backup the current crontab to a file.

```bash
crontab -l > crontab-backup.txt
```

## Cron Expression Format

`* * * * * <command>` — Format: minute (0-59) hour (0-23) day-of-month (1-31) month (1-12) day-of-week (0-7, 0 and 7 = Sunday).

```bash
30 2 * * * /usr/local/bin/backup.sh
```

`*/n` — Step value: run every n intervals.

```bash
*/5 * * * * (every 5 minutes)
```

`n,n,n` — List: run at specific values.

```bash
0 8,12,18 * * * (at 8:00, 12:00, 18:00)
```

`n-n` — Range: run for all values in the range.

```bash
0 9-17 * * 1-5 (every hour 9-17, Mon-Fri)
```

`n-n/s` — Range with step: run every s-th value within the range.

```bash
0-30/10 * * * * (at 0, 10, 20, 30 past)
```

## Special Strings

`@reboot <command>` — Run once at system startup.

```bash
@reboot /home/user/start-service.sh
```

`@yearly <command>` — Run once a year (equivalent to 0 0 1 1 *).

```bash
@yearly /usr/local/bin/annual-report.sh
```

`@monthly <command>` — Run once a month (equivalent to 0 0 1 * *).

```bash
@monthly /usr/local/bin/monthly-cleanup.sh
```

`@weekly <command>` — Run once a week (equivalent to 0 0 * * 0).

```bash
@weekly /usr/local/bin/weekly-backup.sh
```

`@daily <command>` — Run once a day (equivalent to 0 0 * * *).

```bash
@daily /usr/local/bin/logrotate.sh
```

`@hourly <command>` — Run once an hour (equivalent to 0 * * * *).

```bash
@hourly /usr/local/bin/check-health.sh
```

## Common Schedules

`* * * * *` — Every minute.

```bash
* * * * * /usr/local/bin/monitor.sh
```

`*/5 * * * *` — Every 5 minutes.

```bash
*/5 * * * * /usr/local/bin/check-queue.sh
```

`*/15 * * * *` — Every 15 minutes.

```bash
*/15 * * * * /usr/local/bin/sync-data.sh
```

`0 * * * *` — Every hour (at minute 0).

```bash
0 * * * * /usr/local/bin/hourly-report.sh
```

`0 0 * * *` — Every day at midnight.

```bash
0 0 * * * /usr/local/bin/daily-backup.sh
```

`0 2 * * *` — Every day at 2:00 AM.

```bash
0 2 * * * /usr/local/bin/maintenance.sh
```

`0 9-17 * * 1-5` — Every hour during business hours (Mon-Fri, 9-17).

```bash
0 9-17 * * 1-5 /usr/local/bin/business-check.sh
```

`0 0 * * 0` — Every Sunday at midnight.

```bash
0 0 * * 0 /usr/local/bin/weekly-cleanup.sh
```

`0 0 1 * *` — First day of every month at midnight.

```bash
0 0 1 * * /usr/local/bin/monthly-report.sh
```

`30 4 1,15 * *` — At 4:30 AM on the 1st and 15th of every month.

```bash
30 4 1,15 * * /usr/local/bin/biweekly-task.sh
```

## Output & Logging

`* * * * * <command> >> /var/log/cron.log 2>&1` — Redirect both stdout and stderr to a log file (append).

```bash
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
```

`* * * * * <command> > /dev/null 2>&1` — Suppress all output (no email, no log).

```bash
*/5 * * * * /usr/local/bin/check.sh > /dev/null 2>&1
```

`MAILTO="user@example.com"` — Set the email recipient for cron output (place at top of crontab).

```bash
MAILTO="admin@example.com"
```

`MAILTO=""` — Disable email notifications for all cron jobs.

```bash
MAILTO=""
```

`* * * * * <command> 2>&1 | logger -t mycron` — Send output to syslog with a custom tag.

```bash
0 * * * * /usr/local/bin/task.sh 2>&1 | logger -t hourly-task
```

## Environment Variables

`PATH=/usr/local/bin:/usr/bin:/bin` — Set the PATH for cron jobs (cron uses a minimal PATH by default).

```bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
```

`SHELL=/bin/bash` — Set the shell used to run cron commands (default is /bin/sh).

```bash
SHELL=/bin/bash
```

`HOME=/home/user` — Set the home directory for cron jobs.

```bash
HOME=/home/deploy
```

`* * * * * . /home/user/.profile && <command>` — Source the user's profile to get the full environment before running.

```bash
0 * * * * . /home/deploy/.profile && /usr/local/bin/task.sh
```

`* * * * * env VAR=value <command>` — Set a variable inline for a specific cron job.

```bash
0 2 * * * env NODE_ENV=production /usr/local/bin/node /app/worker.js
```

## System Cron Directories

`/etc/crontab` — System-wide crontab file. Has an extra user field after the time fields.

```bash
0 * * * * root /usr/local/bin/system-check.sh
```

`/etc/cron.d/` — Directory for additional system crontab files (same format as /etc/crontab).

```bash
ls /etc/cron.d/
```

`/etc/cron.hourly/` — Scripts in this directory are run every hour by anacron/run-parts.

```bash
cp myscript.sh /etc/cron.hourly/
```

`/etc/cron.daily/` — Scripts run once a day.

```bash
ls /etc/cron.daily/
```

`/etc/cron.weekly/` — Scripts run once a week.

```bash
ls /etc/cron.weekly/
```

`/etc/cron.monthly/` — Scripts run once a month.

```bash
ls /etc/cron.monthly/
```

## Troubleshooting

`grep CRON /var/log/syslog` — Check the syslog for cron execution logs.

```bash
grep CRON /var/log/syslog | tail -20
```

`journalctl -u cron` — View cron logs via systemd journal.

```bash
journalctl -u cron --since today
```

`systemctl status cron` — Check if the cron daemon is running.

```bash
systemctl status cron
```

`run-parts --test /etc/cron.daily` — Test which scripts in a cron directory would be executed.

```bash
run-parts --test /etc/cron.daily
```

`* * * * * /usr/bin/env > /tmp/cron-env.txt` — Debug cron environment by dumping all environment variables.

```bash
* * * * * /usr/bin/env > /tmp/cron-env.txt 2>&1
```

`cat /etc/cron.allow` — Check which users are allowed to use crontab (if file exists).

```bash
cat /etc/cron.allow
```

`cat /etc/cron.deny` — Check which users are denied crontab access (if file exists).

```bash
cat /etc/cron.deny
```

<!-- PROSE:outro -->
## Conclusion

crontab handles recurring tasks reliably in the background – for everyday work you rarely need more than `crontab -e` to edit, `crontab -l` to inspect, and the familiar five-field syntax. The most common problems come not from the schedule but from the environment: cron starts jobs with a minimal `PATH` and without your login profile, so use absolute paths or set `PATH` explicitly. A literal `%` in a command is interpreted as a newline by cron and must be escaped as `\%`. Log your output (`>> logfile 2>&1`) or set `MAILTO`, otherwise failures pass silently. And mind `crontab -r`: it deletes your entire crontab with no confirmation and sits right next to `crontab -e` on the keyboard – back it up first with `crontab -l > backup.txt`.

## Further Reading

- [Debian Wiki: cron](https://wiki.debian.org/cron) – how cron is set up on Debian/Ubuntu, including the system cron directories
- [crontab.guru](https://crontab.guru/) – interactive helper to build and decode cron expressions
<!-- PROSE:outro:end -->

## Related Commands

- [at](https://www.jpkc.com/db/en/cheatsheets/shell-system/at/) – schedules one-off jobs at a specific time instead of recurring
- [systemctl](https://www.jpkc.com/db/en/cheatsheets/shell-system/systemctl/) – manages systemd services and timers as a modern cron alternative
- [journalctl](https://www.jpkc.com/db/en/cheatsheets/shell-system/journalctl/) – searches the systemd journal, e.g. for cron executions

