$ run as a normal user# run as root (or with sudo)
Skills in this chapter
- Schedule system jobs with cron, systemd timers and tmpfiles
Use the system cron files
System cron jobs live in files, not in crontab -e. Their lines have one extra field: the user the job runs as.
# Run the backup as root every night at 01:30
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
30 1 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * apache /usr/local/bin/clean-sessions.sh| Place | Use |
|---|---|
/etc/crontab | The main system table (do not change it: package updates may) |
/etc/cron.d/NAME | One file per job or per application — use this |
/etc/cron.hourly/, cron.daily/, cron.weekly/, cron.monthly/ | Scripts run once per hour / day / week / month |
/var/spool/cron/USER | The crontabs of the users (made by crontab -e) |
ls /etc/cron.d/ /etc/cron.daily/
install -m 755 cleanup.sh /etc/cron.daily/cleanup
run-parts --test /etc/cron.dailyWatch out
Scripts in cron.daily/ must be executable and their names must not have a dot — cleanup, not cleanup.sh. Otherwise run-parts skips them.
Catch up missed jobs with anacron
anacron runs the daily, weekly and monthly scripts even when the machine was off at the planned time. It remembers the last run of each.
# 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| Field | Meaning |
|---|---|
| period | Run every N days (@monthly = once a month) |
| delay | Wait N minutes after anacron starts (spreads the load) |
| job-id | Name; the date of the last run is saved in /var/spool/anacron/JOB-ID |
| command | What to run |
START_HOURS_RANGE=3-22 in the same file limits the hours when anacron may start jobs.
List and read systemd timers
Many RHEL jobs are timers today: dnf-makecache, logrotate, fstrim, systemd-tmpfiles-clean. list-timers shows when each one runs next.
systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-10-27 13:02:11 +03 21min Mon 2026-10-27 12:02:11 +03 38min dnf-makecache.timer dnf-makecache.service
Tue 2026-10-28 00:00:00 +03 11h Mon 2026-10-27 00:00:00 +03 12h logrotate.timer logrotate.service
Tue 2026-10-28 08:15:00 +03 19h Mon 2026-10-27 08:15:00 +03 4h 25min systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
systemctl list-timers --all
systemctl cat logrotate.timerWrite your own system timer
A timer needs two units with the same name: NAME.service (what to run) and NAME.timer (when). Put them in /etc/systemd/system/.
[Unit]
Description=Nightly backup of /etc and /srv
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Nice=10[Unit]
Description=Run the backup every night
[Timer]
OnCalendar=*-*-* 01:30:00
RandomizedDelaySec=15min
Persistent=true
[Install]
WantedBy=timers.targetsystemctl daemon-reload
systemctl enable --now backup.timer
systemctl list-timers backup.timer
systemctl start backup.service
journalctl -u backup.service -n 20Exam tip
You enable the timer, not the service. Start the service by hand once (systemctl start backup.service) to test it.
Write the right time for OnCalendar
OnCalendar uses the form DayOfWeek Year-Month-Day Hour:Minute:Second. * means "every". systemd-analyze calendar checks it for you.
| Value | Runs |
|---|---|
daily / weekly / monthly | At 00:00 every day / Monday / first day |
*-*-* 02:30:00 | Every day at 02:30 |
Mon..Fri 08:00 | Work days at 08:00 |
*-*-01 04:00 | The first day of every month at 04:00 |
*:0/15 | Every 15 minutes |
Sat,Sun 10:00 | Weekends at 10:00 |
systemd-analyze calendar 'Mon..Fri 08:00'
Original form: Mon..Fri 08:00
Normalized form: Mon..Fri *-*-* 08:00:00
Next elapse: Tue 2026-10-28 08:00:00 +03
systemd-analyze calendar --iterations=3 '*:0/15'Other timer options: OnBootSec=10min (10 minutes after boot), OnUnitActiveSec=1h (one hour after the last run).
Manage temporary files with systemd-tmpfiles
systemd-tmpfiles creates folders and files at boot and deletes old files on a schedule. Rules are lines in tmpfiles.d files.
# Type Path Mode User Group Age
d /run/myapp 0755 myapp myapp -
d /var/tmp/myapp 0750 myapp myapp 7d
f /run/myapp/ready 0644 myapp myapp -| Type | Meaning |
|---|---|
d | Create the folder; with an age, delete files in it that are older |
D | Like d, but empty it at every boot |
f / F | Create a file / create it and empty it |
L | Create a symbolic link |
x | Do not clean this path (an exception) |
systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf
systemd-tmpfiles --clean /etc/tmpfiles.d/myapp.conf
cat /usr/lib/tmpfiles.d/tmp.conf
q /tmp 1777 root root 10d
q /var/tmp 1777 root root 30d
systemctl status systemd-tmpfiles-clean.timerRemember
Package rules are in /usr/lib/tmpfiles.d/. Your own rules (and changes) go to /etc/tmpfiles.d/ — a file with the same name there replaces the package file.
Exam tip
"Files in /var/tmp/myapp older than 7 days must be removed" → one d line with 7d in /etc/tmpfiles.d/, then test with systemd-tmpfiles --clean.