Intermediate · 12 min · practise every command in the built-in terminal

systemd Timers — Scheduled Jobs, the systemd Way

cron runs commands on a schedule. On a systemd system there's a second way: a timer that starts a service. Debian uses timers for its own jobs:

systemctl list-timers
NEXT                            LEFT LAST                            PASSED UNIT              ACTIVATES
Sat 2026-10-31 00:00:00 CET 2h 54min Fri 2026-10-30 00:00:00 CET    21h ago logrotate.timer   logrotate.service
Sun 2026-11-01 03:10:22 CET 1 day 6h Sun 2026-10-25 03:10:22 CET 5 days ago e2scrub_all.timer e2scrub_all.service

NEXT and LEFT: when it runs next. LAST and PASSED: when it last ran. ACTIVATES: the service it starts.

A job in two files

Your backup script is ready: ~/scripts/docs-backup.sh packs ~/documents into ~/backups.

1. The service — what to run, /etc/systemd/system/docs-backup.service:

[Unit]
Description=Back up ~/documents

[Service]
Type=oneshot
User=student
ExecStart=/home/student/scripts/docs-backup.sh

Type=oneshot: a job that runs to its end, not a server that keeps running. User= — not as root.

sudo nano /etc/systemd/system/docs-backup.service
sudo systemctl daemon-reload

daemon-reload makes systemd read the new and changed unit files.

Try it by hand first — and read what it printed:

sudo systemctl start docs-backup.service
systemctl status docs-backup.service
journalctl -u docs-backup.service

Everything the script prints lands in the journal, with the time — no more lost cron mail.

2. The timer — when, /etc/systemd/system/docs-backup.timer (same name, .timer):

[Unit]
Description=Back up ~/documents every night

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true

[Install]
WantedBy=timers.target

Persistent=true: if the server was off at 02:30, the job runs as soon as it's back.

sudo nano /etc/systemd/system/docs-backup.timer
sudo systemctl daemon-reload
sudo systemctl enable --now docs-backup.timer
systemctl list-timers docs-backup.timer

You enable the timer, not the service — the service has no [Install] section, the timer starts it.

OnCalendar

DayOfWeek Year-Month-Day Hour:Minute:Second — each part may be *, a list 1,15 or a range 9..17:

OnCalendarWhen
dailyevery day at 00:00
*-*-* 02:30:00every day at 02:30
Mon..Fri 09:00weekdays at 09:00
Sun 03:00Sundays at 03:00
*-*-01 04:00the first of each month
*:0/15every 15 minutes

Not sure? Ask systemd:

systemd-analyze calendar 'Mon..Fri 09:00'
  Original form: Mon..Fri 09:00
Normalized form: Mon..Fri *-*-* 09:00:00
    Next elapse: Mon 2026-11-02 09:00:00 CET

Instead of a calendar, a timer can count from something: OnBootSec=15min (after boot), OnUnitActiveSec=1h (an hour after the last run).

cron or a timer?

cronsystemd timer
Set upone line in crontab -etwo small files
Outputmailed, or lostin the journal
Missed while offskippedPersistent=true catches up
Test it nowrun the scriptsystemctl start NAME.service
See the schedulecrontab -lsystemctl list-timers

💡 For a quick personal job cron is fine. For anything a server depends on — backups, cleanups, reports — a timer gives you logs, status and catch-up for free.

Practice tasks

  1. List the timers on this system
  2. Ask systemd what 'Mon..Fri 09:00' means
  3. Write the service /etc/systemd/system/docs-backup.service: a oneshot that runs ~/scripts/docs-backup.sh as student
  4. Run the service once by hand, then read its output in the journal
  5. Write the timer /etc/systemd/system/docs-backup.timer: every night at 02:30
  6. Turn the timer on — now, and after every reboot
  7. See when your backup runs next

Commands in this lesson

Services & systemd