First the service
Write the work as an ordinary oneshot service — a job that runs and finishes. This one just appends a line to a file:
sudo tee /etc/systemd/system/report.service > /dev/null <<'EOF'
[Unit]
Description=Write a report
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'date >> /var/tmp/report.log'
EOF
cat /etc/systemd/system/report.serviceIn the terminal
student@vulntech:~$ sudo tee /etc/systemd/system/report.service > /dev/null <<'EOF' > [Unit] > Description=Write a report > > [Service] > Type=oneshot > ExecStart=/bin/sh -c 'date >> /var/tmp/report.log' > EOF [sudo] password for student: student@vulntech:~$ cat /etc/systemd/system/report.service [Unit] Description=Write a report [Service] Type=oneshot ExecStart=/bin/sh -c 'date >> /var/tmp/report.log'
Then the timer
The timer has a [Timer] section with the schedule and an [Install] section pointing at timers.target so it starts at boot. OnUnitActiveSec=1h means “one hour after each run”; OnCalendar (next lesson) gives clock times:
sudo tee /etc/systemd/system/report.timer > /dev/null <<'EOF'
[Unit]
Description=Run report hourly
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
EOF
cat /etc/systemd/system/report.timerIn the terminal
student@vulntech:~$ sudo tee /etc/systemd/system/report.timer > /dev/null <<'EOF' > [Unit] > Description=Run report hourly > > [Timer] > OnCalendar=hourly > Persistent=true > > [Install] > WantedBy=timers.target > EOF [sudo] password for student: student@vulntech:~$ cat /etc/systemd/system/report.timer [Unit] Description=Run report hourly [Timer] OnCalendar=hourly Persistent=true [Install] WantedBy=timers.target
Enable the timer, not the service
You start and enable the timer — the service is left alone, because the timer starts it on schedule. enable --now turns it on now and at boot:
sudo systemctl daemon-reload
sudo systemctl enable --now report.timer
systemctl is-active report.timer
systemctl list-timers report.timer --no-pagerIn the terminal
student@vulntech:~$ sudo systemctl daemon-reload [sudo] password for student: student@vulntech:~$ sudo systemctl enable --now report.timer Created symlink /etc/systemd/system/timers.target.wants/report.timer → /etc/systemd/system/report.timer. student@vulntech:~$ systemctl is-active report.timer active student@vulntech:~$ systemctl list-timers report.timer --no-pager NEXT LEFT LAST PASSED UNIT ACTIVATES Sun 2026-10-18 08:00:00 UTC 58min left - - report.timer report.service 1 timers listed. Pass --all to see loaded but inactive timers, too.
Common mistake: Enable the
.timer, not the.service. If you enable the service it runs once at boot and never again; the timer is what makes it repeat on schedule.
Remember: A scheduled job is a
oneshotservice plus a.timerwith a[Timer]schedule andWantedBy=timers.target.daemon-reload, thenenable --now the.timer.