Science and technology

Analyzing systemd calendar and timespans

In my earlier seven articles on this sequence about systemd, and particularly within the most recent article, time and date have come up in a number of contexts. systemd makes use of calendar time, specifying a number of moments in time to set off occasions (corresponding to a backup program), in addition to timestamped entries within the journal. It can even use timespans, which outline the period of time between two occasions however should not immediately tied to particular calendar occasions.

In this text, I’ll look in additional element at how time and date are used and laid out in systemd. Also, as a result of systemd makes use of two barely totally different, non-compatible time codecs, I’ll clarify how and when they’re used.

Definitions

Following are some vital time- and calendar-related systemd phrases to know:

  • Absolute timestamp: A single unambiguous and distinctive cut-off date outlined within the format YYYY-MM-DD HH:MM:SS. The timestamp format specifies deadlines when occasions are triggered by timers. An absolute timestamp can signify solely a single cut-off date, corresponding to 2025-04-15 13:21:05.

  • Accuracy is the standard of closeness to the true time; in different phrases, how near the desired calendar time an occasion is triggered by a timer. The default accuracy for systemd timers is outlined as a one-minute timespan that begins on the outlined calendar time. For instance, an occasion specified to happen on the OnCalendar time of 09:52:17 may be triggered at any time between then and 09:53:17.

  • Calendar occasions are a number of particular occasions specified by a systemd timestamp within the format YYYY-MM-DD HH:MM:SS. It could be a single cut-off date or a sequence of factors which can be well-defined and for which the precise occasions may be calculated. systemd journals use timestamps to mark every occasion with the precise time it occurred.

    In systemd, precise time is specified within the timestamp format YYYY-MM-DD HH:MM:SS. When solely the YYYY-MM-DD portion is specified, the time defaults to 00:00:00. When solely the HH:MM:SS portion is specified, the date is the following calendar occasion of that point. If the time specified is earlier than the present time, the following occasion can be tomorrow, and if the desired time is later than the present time, the following occasion can be as we speak. This is the format systemd timers use to precise OnCalendar occasions.

    Recurring calendar occasions may be specified utilizing particular characters and codecs that signify fields with a number of worth matches. For instance, 2026-08-15..25 12:15:00 represents 12:15pm on the 15th by way of the 25th of August 2026 and would set off 11 matches. Calendar occasions may also be specified with an absolute timestamp.

  • Timespan is the period of time between two occasions or the period of one thing like an occasion or the time between two occasions. Timespans can be utilized to specify the specified accuracy for an occasion to be triggered by a timer and to outline the time to elapse between occasions. systemd acknowledges the next time models:

    • usec, us, µs
    • msec, ms
    • seconds, second, sec, s
    • minutes, minute, min, m
    • hours, hour, hr, h
    • days, day, d
    • weeks, week, w
    • months, month, M (outlined as 30.44 days)
    • years, 12 months, y (outlined as 365.25 days)

The systemd.time(7) man web page has an entire description of time and date expressions in timers and different systemd instruments.

Calendar occasion expressions

Calendar occasion expressions are a key a part of triggering timers at repetitive occasions. systemd and its timers do not use the identical type for time and date expressions as crontab makes use of. systemd can be extra versatile than crontab and permits fuzzy dates and occasions just like the at command.

The format OnCalendar= makes use of for calendar occasion expressions is DOW YYYY-MM-DD HH:MM:SS. DOW (day of the week) is optionally available, and different fields can use an asterisk (*) to match any worth for that place. If the time shouldn’t be specified, it’s assumed to be 00:00:00. If the date shouldn’t be specified however the time is, the following match may be as we speak or tomorrow, relying upon the present time. All the varied calendar time-expression codecs are transformed to a normalized type, and the systemd-analyze calendar command reveals the normalized type of the time expression.

systemd gives a superb instrument for validating and analyzing calendar occasions utilized in an expression. The systemd-analyze calendar instrument parses a calendar time occasion expression and gives the normalized type and different info, such because the date and time of the following “elapse” (i.e., match) and the approximate period of time earlier than it reaches the set off time.

Note: All the next instructions may be carried out by non-root customers and the occasions for “Next elapse” and “UTC” will differ primarily based in your native time zone.

First, have a look at the syntax of the systemd-analyze calendar command. Start with a date sooner or later and not using a time. Because all of the date unit fields are explicitly specified, it is a one-time occasion:

[scholar@testvm1 ~]$ systemd-analyze calendar 2030-06-17
  Original type: 2030-06-17                
Normalized type: 2030-06-17 00:00:00        
    Next elapse: Mon 2030-06-17 00:00:00 EDT
       (in UTC): Mon 2030-06-17 04:00:00 UTC
       From now: 10 years Zero months left    

Add a time (on this instance, the date and time are analyzed individually as non-related entities):

[root@testvm1 system]# systemd-analyze calendar 2030-06-17 15:21:16
  Original type: 2030-06-17                
Normalized type: 2030-06-17 00:00:00        
    Next elapse: Mon 2030-06-17 00:00:00 EDT
       (in UTC): Mon 2030-06-17 04:00:00 UTC
       From now: 10 years Zero months left    

  Original type: 15:21:16                  
Normalized type: *-*-* 15:21:16            
    Next elapse: Mon 2020-06-15 15:21:16 EDT
       (in UTC): Mon 2020-06-15 19:21:16 UTC
       From now: 3h 55min left

To analyze the date and time as a single entity, enclose them collectively in quotes:

[scholar@testvm1 system]# systemd-analyze calendar "2030-06-17 15:21:16"
Normalized type: 2030-06-17 15:21:16        
    Next elapse: Mon 2030-06-17 15:21:16 EDT
       (in UTC): Mon 2030-06-17 19:21:16 UTC
       From now: 10 years Zero months left  

Specify one time sooner than the present time and one later. In this instance, the present time is 16:16 on 2019-05-15:

[scholar@testvm1 ~]$ systemd-analyze calendar 15:21:16 22:15
  Original type: 15:21:16
Normalized type: *-*-* 15:21:16
    Next elapse: Fri 2019-05-17 15:21:16 EDT
       (in UTC): Fri 2019-05-17 19:21:16 UTC
       From now: 23h left

  Original type: 22:15
Normalized type: *-*-* 22:15:00
    Next elapse: Thu 2019-05-16 22:15:00 EDT
       (in UTC): Fri 2019-05-17 02:15:00 UTC
       From now: 5h 59min left

The systemd-analyze calendar instrument doesn’t work on timestamps. So issues like “tomorrow” or “today” will trigger errors if you happen to use them with the calendar sub-command as a result of they’re timestamps reasonably than OnCalendar time codecs:

[scholar@testvm1 ~]$ systemd-analyze calendar "tomorrow"
Failed to parse calendar expression 'tomorrow': Invalid argument
Hint: this expression is a legitimate timestamp. Use 'systemd-analyze timestamp "tomorrow"' as a substitute?

The time period “tomorrow” will all the time resolve to tomorrow’s date and a time of 00:00:00. You should use the normalized expression format, YYYY-MM-DD HH:MM:SS, for this instrument to work in calendar mode. Despite this, the systemd-analyze calendar instrument can nonetheless enable you perceive the construction of the calendar time expressions utilized by systemd timers. I like to recommend studying the systemd.time(7) man web page for a greater understanding of the time codecs that can be utilized with systemd timers.

Why would utilizing an announcement like OnCalendar=tomorrow fail when utilized in a timer?

Timestamps

Whereas calendar occasions can be utilized to match single or a number of deadlines, timestamps unambiguously signify a single cut-off date. For instance, timestamps within the systemd journal seek advice from a exact second when every logged occasion happens:

[scholar@testvm1 ~]$ journalctl -S as we speak
Hint: You are at the moment not seeing messages from different customers and the system.
      Users in teams 'adm', 'systemd-journal', 'wheel' can see all messages.
      Pass -q to show off this discover.
-- Logs start at Wed 2020-06-17 10:08:41 EDT, finish at Wed 2020-06-17 10:13:55 EDT. --
Jun 17 10:08:41 testvm1.each.org systemd[1137785]: Started Mark boot as profitable after the consumer session has run 2 minutes.
Jun 17 10:08:41 testvm1.each.org systemd[1137785]: Started Daily Cleanup of User's Temporary Directories.
Jun 17 10:08:41 testvm1.each.org systemd[1137785]: Reached goal Paths.
Jun 17 10:08:41 testvm1.each.org systemd[1137785]: Reached goal Timers.
<SNIP>
Jun 17 10:13:55 testvm1.each.org systemd[1137785]: systemd-tmpfiles-clean.service: Succeeded.
Jun 17 10:13:55 testvm1.each.org systemd[1137785]: Finished Cleanup of User'
s Temporary Files and Directories.

The systemd-analyze timestamp command can be utilized to investigate timestamp expressions the identical approach it analyzes calendar expressions. Here is an instance from the journal information stream:

[scholar@testvm1 ~]$ systemd-analyze timestamp "Jun 17 10:08:41"
Failed to parse "Jun 17 10:08:41": Invalid argument
[scholar@testvm1 ~]$ systemd-analyze timestamp Jun 17 10:08:41
Failed to parse "Jun": Invalid argument

Failed to parse "17": Invalid argument
Hint: this expression is a legitimate timespan. Use 'systemd-analyze timespan "17"' as a substitute?

  Original type: 10:08:41                  
Normalized type: Wed 2020-06-17 10:08:41 EDT
       (in UTC): Wed 2020-06-17 14:08:41 UTC
   UNIX seconds: @1592402921                
       From now: 11min in the past

Why is the information copied from the journal not thought-about to be a legitimate timestamp? I do not know. It appears fairly dumb to print the timestamps for the journal in a format that can not be utilized by the instrument designed to investigate timestamps. But have a look at the time specified as the start of the log:

[scholar@testvm1 ~]$ systemd-analyze timestamp "Wed 2020-06-17 10:08:41"
  Original type: Wed 2020-06-17 10:08:41    
Normalized type: Wed 2020-06-17 10:08:41 EDT
       (in UTC): Wed 2020-06-17 14:08:41 UTC
   UNIX seconds: @1592402921                
       From now: 15min in the past                  
[scholar@testvm1 ~]$

OK, so that point is a legitimate timestamp. The secret’s that the systemd-analyze instrument solely acknowledges the DOW YYYY-MM-DD HH:MM:SS format. As the error messages state, it doesn’t acknowledge month names or standalone days of the month, corresponding to 17. It may be very exacting as a result of the one approach to make sure occasions are triggered by timers at desired deadlines or intervals is to be utterly correct with how they’re specified.

Any unambiguously expressed time, corresponding to 2020-06-17 10:08:41, is a timestamp as a result of it may solely happen as soon as. A timestamp that may happen sooner or later may also be utilized in a systemd timer, and that timer will solely set off its outlined motion as soon as.

A time expressed considerably extra ambiguously, corresponding to 2025-*-* 22:15:00, can solely be a calendar time used within the OnCalendar assertion in a timer unit file. This expression will set off an occasion on daily basis within the 12 months 2025 at 22:15:00 (10:15:00pm).

But nonetheless—why not use legitimate timestamps within the journal output? I nonetheless do not know, however with a little bit of command-line manipulation, you possibly can convert the default time show into legitimate timestamps. The journalctl command instrument has some choices that may show the timestamps in a format you possibly can simply use with the systemd-analyze instrument:

[root@testvm1 ~]# journalctl -o short-full
<SNIP>
Fri 2020-06-26 12:51:36 EDT testvm1.each.org systemd[1]: Finished Update UTMP about System Runlevel Changes.
Fri 2020-06-26 12:51:36 EDT testvm1.each.org systemd[1]: Startup completed in 2.265s (kernel) + four.883s (initrd) + 22.645s (userspace) = 29.793s.
Fri 2020-06-26 12:51:36 EDT testvm1.each.org audit[1]: SERVICE_START pid=1 uid=Zero auid=4294967295 ses=4294967295 msg='unit=systemd-update-utmp-runlevel>
Fri 2020-06-26 12:51:36 EDT testvm1.each.org audit[1]: SERVICE_STOP pid=1 uid=Zero auid=4294967295 ses=4294967295 msg='
unit=systemd-update-utmp-runlevel >
Fri 2020-06-26 12:51:36 EDT testvm1.each.org crond[959]: (CRON) INFO (working with inotify assist)
Fri 2020-06-26 12:51:36 EDT testvm1.each.org ModemManager[759]: <information>  Couldn't verify assist for gadget '/sys/gadgets/pci0000:00/0000:00:03.Zero': not >
Fri 2020-06-26 12:51:37 EDT testvm1.each.org VBoxService[804]: 16:51:37.196960 timesync vgsvcTimeSyncWorker: Radical visitor time change: -14 388 436 32>
Fri 2020-06-26 12:51:39 EDT testvm1.each.org chronyd[827]: Selected supply 192.168.Zero.52
Fri 2020-06-26 12:51:39 EDT testvm1.each.org chronyd[827]: System clock TAI offset set to 37 seconds
<SNIP>

You can now use the timestamps like this:

[root@testvm1 ~]# systemd-analyze timestamp "2020-06-26 12:51:36"
  Original type: 2020-06-26 12:51:36        
Normalized type: Fri 2020-06-26 12:51:36 EDT
       (in UTC): Fri 2020-06-26 16:51:36 UTC
   UNIX seconds: @1593190296                
       From now: 2h 37min in the past              
[root@testvm1 ~]#

You can even show the journal timestamps in a monotonic format that reveals the variety of seconds since boot:

[root@testvm1 ~]# journalctl -o short-monotonic
[    Zero.000000] testvm1.each.org kernel: Linux model 5.6.6-300.fc32.x86_64 (mockbuild@bkernel03.phx2.fedoraproject.org) (gcc model 10.Zero.1 20200328 >
[    Zero.000000] testvm1.each.org kernel: Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.6.6-300.fc32.x86_64 root=/dev/mapper/VG01-root ro resume=/dev/>
[    Zero.000000] testvm1.each.org kernel: x86/fpu: Supporting XSAVE function 0x001: 'x87 floating level registers'
[    Zero.000000] testvm1.each.org kernel: x86/fpu: Supporting XSAVE function 0x002: 'SSE registers'
[    Zero.000000] testvm1.each.org kernel: x86/fpu: Supporting XSAVE function 0x004: 'AVX registers'
[    Zero.000000] testvm1.each.org kernel: x86/fpu: xstate_offset[2]:  576, xstate_sizes[2]:  256
[    Zero.000000] testvm1.each.org kernel: x86/fpu: Enabled xstate options 0x7, context measurement is 832 bytes, utilizing 'normal' format.
[    Zero.000000] testvm1.each.org kernel: BIOS-provided bodily RAM map:
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x0000000000100000-0x00000000dffeffff] usable
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x00000000dfff0000-0x00000000dfffffff] ACPI information
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x00000000fec0000Zero-0x00000000fec00fff] reserved
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x00000000charge0000Zero-0x00000000charge00fff] reserved
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
[    Zero.000000] testvm1.each.org kernel: BIOS-e820: [mem 0x0000000100000000-0x00000003373fffff] usable
[    Zero.000000] testvm1.each.org kernel: NX (Execute Disable) safety: lively
[    Zero.000000] testvm1.each.org kernel: SMBIOS 2.5 current.
[    Zero.000000] testvm1.each.org kernel: DMI: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[    Zero.000000] testvm1.each.org kernel: Hypervisor detected: KVM
<SNIP>
[28829.016018] testvm1.each.org NetworkManager[760]: <information>  [1593219095.3936] dhcp4 (enp0s3): possibility requested_time_offset => '1'
[28829.016062] testvm1.each.org NetworkManager[760]: <information>  [1593219095.3936] dhcp4 (enp0s3): possibility requested_wpad       => '1'
[28829.016106] testvm1.each.org NetworkManager[760]: <information>  [1593219095.3936] dhcp4 (enp0s3): possibility routers              => '192.168.Zero.254'
[28829.016155] testvm1.each.org NetworkManager[760]: <information>  [1593219095.3936] dhcp4 (enp0s3): possibility subnet_mask          => '255.255.255.Zero'
[28829.016201] testvm1.each.org NetworkManager[760]: <information>  [1593219095.3936] dhcp4 (enp0s3): state modified prolonged -> prolonged
[28829.019332] testvm1.each.org systemd[1]: Starting Network Manager Script Dispatcher Service...
[28829.028205] testvm1.each.org audit[1]: SERVICE_START pid=1 uid=Zero auid=4294967295 ses=4294967295 msg='unit=NetworkManager-dispatcher comm="systemd" >
[28829.028406] testvm1.each.org systemd[1]: Started Network Manager Script Dispatcher Service.
[28839.014035] testvm1.each.org systemd[1]: NetworkManager-dispatcher.service: Succeeded.
[28839.014496] testvm1.each.org audit[1]: SERVICE_STOP pid=1 uid=Zero auid=4294967295 ses=4294967295 msg='
unit=NetworkManager-dispatcher comm="systemd" e>
[29336.998580] testvm1.each.org systemd[1]: Starting system exercise accounting instrument...
[29337.443114] testvm1.each.org audit[1]: SERVICE_START pid=1 uid=Zero auid=4294967295 ses=4294967295 msg='unit=sysstat-collect comm="systemd" exe="/usr/>
[29337.443347] testvm1.each.org audit[1]: SERVICE_STOP pid=1 uid=Zero auid=4294967295 ses=4294967295 msg='
unit=sysstat-collect comm="systemd" exe="/usr/l>
[29337.443404] testvm1.each.org systemd[1]: sysstat-collect.service: Succeeded.
[29337.443504] testvm1.each.org systemd[1]: Finished system exercise accounting instrument.
[29394.784506] testvm1.each.org CROND[2253]: (root) CMD (run-parts /and many others/cron.hourly)
[29394.792113] testvm1.each.org run-parts[2256]: (/and many others/cron.hourly) beginning 0anacron
[29394.799468] testvm1.each.org run-parts[2262]: (/and many others/cron.hourly) completed 0anacron

Read the journalctl man web page for an entire listing of the timestamp format choices (amongst different issues).

Timespans

Timespans are primarily utilized in systemd timers to outline a selected span of time between occasions. This might be used to set off occasions in order that they happen a specified period of time after system startup or after a earlier occasion of the identical occasion. For instance, here’s a pattern expression within the timer unit file to set off an occasion 32 minutes after system startup:

OnStartupSec=32m

The default accuracy for triggering systemd timers is a time window beginning on the specified time and lasting one minute. You can improve set off timespan accuracy to inside a microsecond by including an announcement like the next to the Timer part of the timer-unit file:

AccuracySec=1us

The systemd-analyze timespan command can assist guarantee you’re utilizing a legitimate timespan within the unit file. These samples will get you began:

[scholar@testvm1 ~]$ systemd-analyze timespan 15days
Original: 15days      
      μs: 1296000000000
   Human: 2w 1d        
[scholar@testvm1 ~]$ systemd-analyze timespan "15days 6h 32m"
Original: 15days 6h 32m
      μs: 1319520000000
   Human: 2w 1d 6h 32min

Experiment with these and a few of your personal:

  • "255days 6h 31m"
  • "255days 6h 31m 24.568ms"

Final ideas

Timespans are used to schedule timer occasions a specified interval after an outlined occasion corresponding to startup. Calendar timestamps can be utilized to schedule timer occasions on particular calendar days and occasions, both as one-offs or repeating. Timestamps are additionally used on systemd journal entries, though not in a default format that can be utilized immediately in instruments like systemd-analyze.

All of this was greater than just a bit complicated to me after I began working with systemd timers and creating calendar and timestamp expressions to set off occasions. That was partly due to the same—however not fairly similar—codecs used for specifying timestamps and calendar occasion set off occasions. I hope that this has helped to make clear all of this for you.

In my subsequent article, I’ll discover systemd journaling and associated instruments in additional element

Resources

There is a substantial amount of details about systemd obtainable on the web, however a lot is terse, obtuse, and even deceptive. In addition to the sources talked about on this article, the next webpages provide extra detailed and dependable details about systemd startup.

  • The Fedora Project has an excellent, sensible guide to systemd. It has just about every little thing you might want to know with a view to configure, handle, and keep a Fedora pc utilizing systemd.
  • The Fedora Project additionally has an excellent cheat sheet that cross-references the previous SystemV instructions to comparable systemd ones.
  • For detailed technical details about systemd and the explanations for creating it, try Freedesktop.org‘s description of systemd.
  • Linux.com‘s “More systemd fun” affords extra superior systemd information and tips.

There can be a sequence of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and first developer of systemd. These articles had been written between April 2010 and September 2011, however they’re simply as related now as they had been then. Much of every little thing else good that has been written about systemd and its ecosystem is predicated on these papers.

Most Popular

To Top