Skip to content

~/avetyan.com/cheatsheets

Cheat sheets

crontab and /etc/cron.* cheat sheet

Where cron jobs live on Linux: user crontabs, /etc/crontab, /etc/cron.d and the cron.hourly, daily, weekly and monthly folders, run-parts naming rules and anacron.

6 min read


Cron jobs can hide in six places. This sheet covers where they live and how each place behaves. For the schedule syntax, see the cron cheat sheet.

Where jobs live

PlaceWho edits itUser fieldSchedule

Put your own system jobs in /etc/cron.d/, one file per job. Package upgrades may overwrite /etc/crontab, and a separate file is easy to find, review and remove.

crontab command

bash
crontab -e                              # edit your crontab
crontab -l                              # show it
crontab -l > crontab.bak                # back it up
crontab crontab.bak                     # replace it from a file
crontab -u alice -e                     # edit another user's (root)
crontab -r                              # delete it, with no prompt

-r sits next to -e on the keyboard. Keep a backup, or use crontab -ri where it’s supported, which asks first.

User crontabs are stored in /var/spool/cron/crontabs/<user> on Debian and Ubuntu and in /var/spool/cron/<user> on RHEL and Fedora. Always edit them with crontab, which checks the syntax and tells cron to reload.

/etc/crontab

/etc/crontab on Debian and Ubuntu (excerpt)
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m  h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily; }
47 6    * * 7   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
52 6    1 * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }

This is how the cron.* folders get run. Without anacron, daily jobs run at 06:25. With anacron installed, anacron runs them instead (see below).

/etc/cron.d

/etc/cron.d/db-backup
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[email protected]

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

Debian and Ubuntu use Debian’s cron; RHEL, Rocky, Fedora and Alma use cronie. They check /etc/cron.d files differently:

RuleDebian, Ubuntu (cron)RHEL, Fedora (cronie)

A file that passes both columns works everywhere: owned by root, mode 644, named like db-backup, ending with a newline. Variables at the top of a file apply to every line in it. Each file is separate and doesn’t inherit variables from /etc/crontab.

The cron.* folders

Each folder holds plain executable scripts, with no schedule lines inside. run-parts runs them one after another, in name order.

bash
cat > /etc/cron.daily/cleanup-tmp <<'EOF'
#!/bin/sh
find /var/tmp/app -type f -mtime +7 -delete
EOF
chmod 755 /etc/cron.daily/cleanup-tmp

run-parts --test /etc/cron.daily        # list what would run (Debian)
run-parts --report /etc/cron.daily      # run them now, print what ran
ls -l /etc/cron.daily/
RuleWhy

The two families ship different run-parts programs, and they disagree on names:

Debian, UbuntuRHEL, Fedora

Name scripts without dots, like cleanup-tmp, and they run on both.

run-parts --test /etc/cron.daily lists what would run on either family. If a script that “never runs” isn’t listed, its name or permissions are the problem.

anacron

anacron runs daily, weekly and monthly jobs on machines that aren’t always on, like laptops or VMs that get stopped at night. It remembers when each folder last ran and catches up after a boot.

/etc/anacrontab (typical RHEL/Fedora)
RANDOM_DELAY=45
START_HOURS_RANGE=3-22

#period  delay  job-id        command
1        5      cron.daily    nice run-parts /etc/cron.daily
7        25     cron.weekly   nice run-parts /etc/cron.weekly
@monthly 45     cron.monthly  nice run-parts /etc/cron.monthly
bash
ls /var/spool/anacron/                  # timestamps of the last runs
anacron -T                              # check anacrontab syntax
anacron -fn                             # run every job now, ignoring timestamps
DistroWhat runs the folders

So on RHEL, “daily” jobs start some time between 03:00 and 22:00 with a random delay, not at a fixed minute.

Who may use cron

FileEffect

RHEL and Fedora install an empty /etc/cron.deny, so out of the box every user can use crontab there too. Delete that file and only root can.

Root can always use crontab. These files only control the crontab command. A user who is denied later keeps their existing crontab, and its jobs keep running until you remove it with crontab -r -u <user>.

Find every job

bash
for u in $(cut -d: -f1 /etc/passwd); do
  crontab -l -u "$u" 2>/dev/null | grep -v '^#' | sed "s/^/$u: /"
done
cat /etc/crontab
ls -l /etc/cron.d/ /etc/cron.{hourly,daily,weekly,monthly}/
systemctl list-timers --all             # systemd timers do the same job

Run this when taking over a server. Old jobs that nobody remembers are a classic source of 3 a.m. load spikes.

Keep in mind

  • A script in cron.daily that works when you run it by hand but not from cron is almost always the name (a dot), the missing execute bit or PATH.
  • Packages drop their own scripts in these folders: logrotate, man-db, apt and others. Read them before you wonder where a nightly job comes from.
  • For anything with dependencies, retries or logging to the journal, consider a systemd timer.

Comments

Sign in with Google, GitHub or Facebook to comment.

Loading comments…