Ad space (728×90)

systemd Unit Validator

Free systemd unit file validator. Check a .service/.timer/.socket file's sections and a few required-field rules.

← Back to all tools

Why a Timer with no trigger condition is a silent no-op

A [Timer] unit exists specifically to schedule when its paired service runs, but that schedule has to be spelled out explicitly — via OnCalendar= (a calendar-based schedule), OnBootSec= (relative to boot), or OnUnitActiveSec= (relative to the last activation), among a few others. A [Timer] section with none of these present is syntactically valid and will load without complaint from systemd, but it will simply never fire — no error, no log entry calling it out, just a timer that's enabled and running but does nothing forever. That silent-failure mode is exactly why this check exists: catching a missing trigger condition here is far cheaper than discovering three weeks later that a scheduled job never actually ran once.

Why Type= determines whether ExecStart= is required

Most systemd service types (simple, notify, dbus, idle) describe a long-running process, and systemd needs to know what command actually starts that process — hence ExecStart= being required. Type=oneshot is the deliberate exception: a oneshot service is expected to run a command to completion and exit, and while it commonly still uses ExecStart=, the service type itself doesn't strictly require it the way the long-running types do, since a oneshot unit can legitimately consist of only ExecStartPre=/ExecStartPost= actions with no primary ExecStart= at all in some configurations. Checking this conditionally on the actual declared Type= — rather than requiring ExecStart= unconditionally — avoids flagging valid oneshot units as broken.