← All notes

Linux Field notes

Scheduling work with systemd timers

A timer decides when work becomes eligible to run. A service describes the work itself. Keeping those responsibilities separate makes scheduled tasks easier to inspect and troubleshoot.

Start with a small service

A timer normally activates the service with the same base name: cache-sweep.timer starts cache-sweep.service. A different target can be selected with Unit=. For a short task that runs and exits, Type=oneshot is a useful service type. Avoid RemainAfterExit=yes for a repeating task, because a service left active will not be started again by later timer events.

This user service cleans expired user temporary files according to configured rules. The command reads the applicable rules; it does not mean every temporary file is removed. Inspect those rules before enabling cleanup on an unfamiliar machine.

[Unit]
Description=Clean expired user temporary files

[Service]
Type=oneshot
ExecStart=/usr/bin/systemd-tmpfiles --user --clean

Choose the right clock

OnCalendar= uses calendar time. A daily expression follows the machine's configured time zone unless a zone is explicitly included. Monotonic settings such as OnBootSec= and OnUnitActiveSec= measure intervals from events instead. Decide whether the task belongs to a civil schedule or to elapsed running time before choosing an expression.

[Unit]
Description=Run user temporary-file cleanup daily

[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=10m

[Install]
WantedBy=timers.target

Persistent=true lets a calendar timer catch up after it was inactive and missed a scheduled event. It triggers a catch-up run rather than replaying every missed occurrence. The random delay spreads work over time, while AccuracySec= separately permits timer coalescing. Neither setting promises execution at an exact second.

Check the result

Place both units in the user unit directory, reload the user manager, and enable the timer. These commands refer to the two files described above:

systemctl --user daemon-reload
systemctl --user enable --now cache-sweep.timer
systemctl --user list-timers --all
journalctl --user -u cache-sweep.service

The timer list shows the next and previous triggers; the service journal explains whether the work succeeded. A timer firing is not proof of a successful job. User timers also depend on the user manager being available. If work must run without a login session, check the machine's user-manager lifecycle and administrative policy first.