← Start of tutorial

WIUNIX ACADEMY

Reliable systemd timers: missed runs, repeatable jobs and completion intervals

Page 3 of 4. Review the earlier steps and prerequisites before continuing.

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Rocky Linux 10Reviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment3 editable values
07

LET’S BUILD

Find why a triggered job did not complete

Read the service result and journal around the attempted activation. Missing files, syntax errors, a timeout, denied state access or an existing broken marker are application failures rather than timer syntax failures. Preserve the first failure messages before resetting any failed state.

The marker is not a backup verification result. For this fixture, inspect the tiny report and its date. For a real task, use its own validation and recovery procedure before retrying. No journal entry can prove work that the application did not commit.

bash

Terminal on the authorized staging host

systemctl status 'academy-daily-marker.service' --no-pager
systemctl show 'academy-daily-marker.service' -p Result -p ExecMainCode -p ExecMainStatus -p TimeoutStartUSec
sudo journalctl -u 'academy-daily-marker.service' -u 'academy-daily-marker.timer' --since '-1 hour' --no-pager -n 100
sudo ls -la '/var/lib/academy-daily-marker/'
How do I know it worked?

The failure is tied to an exit status, timeout, path or policy message. A nonzero status remains a failed run.

08

LET’S BUILD

Inspect SELinux evidence without disabling enforcement

Correlate AVC messages with this exact service and failure time. Inspect the script label and normal Unix mode. The restorecon invocation is a dry run; it reports proposed changes without applying them. Do not generate broad allow rules or switch to permissive mode. Empty audit output does not exclude a policy problem.

If a restored/custom script has the wrong label, reconcile it with this distribution’s installed file-context policy before applying any correction. DynamicUser does not bypass SELinux or grant permission to unrelated paths.

bash

Authorized staging-host terminal

getenforce
sudo ausearch -m AVC,USER_AVC -ts recent
ls -lZ '/usr/local/libexec/academy-daily-marker.sh'
sudo restorecon -n -v '/usr/local/libexec/academy-daily-marker.sh'
How do I know it worked?

Any suspected denial is tied to evidence; labels and enforcement remain unchanged.

09

LET’S BUILD

Pause future starts without hiding an in-flight job

Disable and stop the timer first when a job fails or the schedule must change. Stopping a timer does not stop its already running service. Inspect the service and let it finish when that is safe; do not assume that disabling the schedule cancels work.

The tiny fixture can safely be stopped if necessary, but a real backup or data migration needs its own interruption procedure. Preserve its partial state and logs. Never kill an unrelated process because its name resembles this job.

bash

Terminal on the authorized staging host

sudo systemctl disable --now 'academy-daily-marker.timer' || exit 1
systemctl show 'academy-daily-marker.timer' -p ActiveState -p SubState
systemctl show 'academy-daily-marker.service' -p ActiveState -p SubState
sudo journalctl -u 'academy-daily-marker.service' --since '-30 min' --no-pager -n 60
How do I know it worked?

The timer is disabled and inactive. The service’s independent running or inactive state is known.

10

LET’S BUILD

Retry only after fixing the cause

For this fixture, correct the named file or policy problem, validate the files again, and retry through the service. Resetting failed state clears systemd’s recorded failure and rate-limit counters; it does not repair a script or roll back partial work.

Inspect the fresh result before re-enabling the timer. Re-enabling a persistent calendar timer can produce a catch-up activation. The marker makes repeat starts for today harmless; a real application needs equivalent behavior before automatic recovery is appropriate.

bash

Terminal on the authorized staging host

sudo systemctl reset-failed 'academy-daily-marker.service' || exit 1
sudo systemctl start 'academy-daily-marker.service' || exit 1
sudo systemctl show 'academy-daily-marker.service' -p Result -p ExecMainStatus
sudo journalctl -u 'academy-daily-marker.service' --since '-10 min' --no-pager -n 60
sudo systemctl enable --now 'academy-daily-marker.timer' || exit 1
systemctl is-enabled --quiet 'academy-daily-marker.timer' || exit 1
systemctl is-active --quiet 'academy-daily-marker.timer' || exit 1
systemctl list-timers --all 'academy-daily-marker.timer'
How do I know it worked?

A fresh run completes or confirms today is already done; only then is the timer waiting again.

11

LET’S BUILD

Optionally change from wall-clock time to a completion interval

Use this alternative only if the rule is “wait thirty minutes after finishing,” not “run at a daily hour.” Stop the timer and wait until the service is inactive before changing the file. Save this lesson’s calendar file once, then replace its complete contents with the next panel; do not append the alternative below the existing calendar settings.

The backup command refuses an existing backup. This is a deliberate change to the fixture, not an instruction to overwrite somebody else’s timer. If you skip this optional alternative, continue to the final acceptance criteria.

bash

Terminal on the authorized staging host

sudo systemctl disable --now 'academy-daily-marker.timer' || exit 1
test "$(systemctl show -p ActiveState --value 'academy-daily-marker.service')" = inactive || exit 1
sudo test ! -e '/etc/systemd/system/academy-daily-marker.timer.calendar-backup' || exit 1
sudo cp -p -- '/etc/systemd/system/academy-daily-marker.timer' '/etc/systemd/system/academy-daily-marker.timer.calendar-backup' || exit 1
sudoedit '/etc/systemd/system/academy-daily-marker.timer' || exit 1
How do I know it worked?

The timer is stopped, the service has finished, and the exact calendar file has a retained backup before editing.

Wait after completion rather than after activation

OnBootSec supplies an initial start five minutes after boot; if that point is already past when the timer starts, it can trigger immediately. OnUnitInactiveSec then measures thirty minutes from the service becoming inactive. It is different from OnUnitActiveSec, whose interval begins at activation.

The alternative has no OnCalendar and no Persistent: it does not recover a list of downtime intervals. Its monotonic clock normally pauses during suspend. The daily marker still writes at most once per UTC day, so frequent intervals demonstrate scheduling without producing repeated business effects.

ini · /etc/systemd/system/academy-daily-marker.timer

Optional replacement file contents — not a shell command

[Unit]
Description=Academy completion-relative schedule

[Timer]
OnBootSec=5min
OnUnitInactiveSec=30min
AccuracySec=1s
Unit=academy-daily-marker.service

[Install]
WantedBy=timers.target
Explore all tutorials ↗