Skip to content

Scheduling

Some system functions run periodically instead of on demand. One such type of recurrence is scheduled activities, like checking for new software updates or rebooting in a nightly maintenance window.

The recurrence itself lives in one place: a named schedule, which any number of features can point at. A schedule has no action of its own, it only says when something should happen, and the feature referencing it decides what happens. Two features can share the same schedule.

YANG support is defined in infix-schedule, which augments ietf-system with a schedules container and builds on the iCalendar recurrence grouping from ietf-schedule (RFC 9922).

Creating a Schedule

Every schedule has a name, which is how features refer to it, and a recurrence rule, which decides when it fires. The example below fires every night at 03:30.

admin@example:/> configure
admin@example:/config/> edit system schedule nightly
admin@example:/config/system/schedule/nightly/> set description "Nightly maintenance window"
admin@example:/config/system/schedule/nightly/> set recurrence frequency daily
admin@example:/config/system/schedule/nightly/> set recurrence byhour 3
admin@example:/config/system/schedule/nightly/> set recurrence byminute 30
admin@example:/config/system/schedule/nightly/> leave

Schedule parameters:

  • name: Unique identifier, 1-64 characters, starting with a letter or digit and otherwise limited to letters, digits, _, . and -. The name is used verbatim by features referencing it
  • enabled: Turn the schedule on or off (default: true). When off, everything that uses it stops running, but the schedule is kept
  • description: Optional human-readable note on the schedule's purpose
  • recurrence: The recurrence rule. A schedule without one is rejected at commit time

Recurrence Rules

The recurrence rule decides when a schedule fires. It is evaluated in the system's local time.

frequency is mandatory and selects the base period:

Frequency Fires
minutely Every minute
hourly Every hour, on the hour
daily Every day at midnight
weekly Every week
monthly The 1st of every month at midnight
yearly January 1st at midnight

interval (default 1) stretches the base period: frequency hourly with interval 6 fires every six hours.

The remaining fields refine that period by pinning one field to specific values:

  • byminute: Minutes within the hour, 0-59
  • byhour: Hours of the day, 0-23
  • byday: Days of the week, by weekday name (monday … sunday)
  • bymonthday: Days of the month, 1-31
  • byyearmonth: Months of the year, 1-12

Each accepts a list, so byhour 8 plus byhour 20 fires twice a day.

Tip

Set frequency to the coarsest period you want, then refine it with the by* fields. A weekly window on Sunday mornings is frequency weekly with byday sunday and byhour 4. Writing the same window as frequency daily would fire every morning.

Limitations

Each schedule is translated into a five-field cron expression, and the YANG model is pruned to the subset cron can express. Everything below is rejected at commit time, so a schedule never fires on the wrong days:

  • secondly frequency. Cron has no seconds field; the finest supported resolution is minutely
  • Combining bymonthday and byday. Cron fires on the union of day-of-month and day-of-week, where RFC 5545 specifies their intersection, so the combination is refused
  • Negative values. "The last Monday of the month" (byday with a direction) and "the last day of the month" (bymonthday -1) have no cron equivalent
  • Start and end bounds. There is no start anchor, no until date and no occurrence count. A schedule recurs until it is disabled
  • Per-schedule time zones, day-of-year, week-of-year and set-position

frequency yearly with an interval above 1 ("every other year") is also not expressible; the interval is ignored in that case.

Using a Schedule

A schedule does nothing on its own, it takes effect when a feature references it through a leaf of type schedule-ref. The reference is validated, so a schedule cannot be deleted while something still uses it, and a typo shows up at commit time instead of at the next occurrence.

These features consume schedules today:

Feature Configuration path
Reboot on a schedule system scheduled-reboot
Update checks system software check-update
Unattended updates system software unattended-update

The example below reboots the system on the nightly schedule created above. Note that scheduled-reboot has no enabled leaf. It is active as soon as it references a schedule; remove the reference or disable the schedule to stop it.

admin@example:/> configure
admin@example:/config/> set system scheduled-reboot schedule nightly
admin@example:/config/> leave

Verifying

To confirm a schedule took effect, look at the generated crontab from the shell. Active schedules become cron jobs owned by the admin user, and the cron daemon runs only while at least one job is active:

admin@example:~$ crontab -l
# Managed by infix-schedule
30 3 * * *  /usr/sbin/reboot

An empty crontab means nothing is scheduled. Check that the consuming feature is enabled, that it names the schedule correctly, and that the schedule itself is enabled.

Note

The crontab is generated and must not be edited by hand. It is rewritten from the configuration on every change.