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.
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
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.
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/'The failure is tied to an exit status, timeout, path or policy message. A nonzero status remains a failed run.
LET’S BUILD
Separate host security policy from timer behavior
A permission denial may come from ordinary file permissions or an active AppArmor profile rather than scheduling. Correlate the kernel messages with this exact job and failure time. Do not disable enforcement to make the exercise pass.
Keep the script root-owned and readable by the dynamic identity. Investigate a missing interpreter or inaccessible path before altering unit security settings. Package security policy and local profiles can differ even when the timer file is identical.
Terminal on the authorized staging host
sudo journalctl -k --since '-15 min' --no-pager -n 100
sudo stat -c '%U %G %a %n' '/usr/local/libexec/academy-daily-marker.sh' '/etc/systemd/system/academy-daily-marker.service'Any host-policy or Unix-permission failure is identified separately; enforcement remains unchanged.
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.
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
The timer is disabled and inactive. The service’s independent running or inactive state is known.
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.
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'
A fresh run completes or confirms today is already done; only then is the timer waiting again.
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.
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
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.
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