I am creating a shell script that needs to calculate e.g. durations between different timestamps.
When shown with list-timers
:
systemctl list-timers my
NEXT LEFT LAST PASSED UNIT ACTIVATES
Sat 2025-05-31 15:32:22 UTC 1min 45s left Sat 2025-05-31 15:29:22 UTC 1min 14s ago my.timer my.service
And in the show
output:
systemctl show my.timer | grep Timestamp
StateChangeTimestamp=Sat 2025-05-31 15:29:22 UTC
StateChangeTimestampMonotonic=7574600882
InactiveExitTimestamp=Sat 2025-05-31 13:23:11 UTC
InactiveExitTimestampMonotonic=3241811
ActiveEnterTimestamp=Sat 2025-05-31 13:23:11 UTC
ActiveEnterTimestampMonotonic=3241811
ActiveExitTimestampMonotonic=0
InactiveEnterTimestampMonotonic=0
ConditionTimestamp=Sat 2025-05-31 13:23:11 UTC
ConditionTimestampMonotonic=3241785
AssertTimestamp=Sat 2025-05-31 13:23:11 UTC
AssertTimestampMonotonic=3241786
None of these are regular UNIX Epoch timestamps. It appears to be a chore to convert the formatted timestamps. The monotonic ones do not seem to be based accurately off anything in particular.
*Timestamp
and *TimestampMonotonic
values?In other words, how to obtain or calculate (what exact base value to add to the "monotonic" values and how to obtain it in order to get) Epoch timestamps?
Systemd uses CLOCK_REALTIME
and CLOCK_MONOTONIC
(of clock_gettime(2)
) on its own, but there's no nice way to get them when implementing a shell script. What is possible is to infer the difference from systemctl show -p KernelTimestamp -p KernelTimestampMonotonic --time unix
(and the monotonic is typically 0 there).
I will not edit this question further, not because I do not need further answers anymore, but because this is how someone will be searching for it - they will need to get timestamps from systemd and they will need them as Epoch timestamps. And some are only available as monotonic, so they will need to convert them. And some do not respect the --timestamp unix
, so they will need DBus or systemd-analyze timestamp
. Also, in a shell script, they will be looking at what they could grab off systemctl show
output.
Hope this helps someone.
Is there a way to get all the values as Epoch timestamps instead?
Use --timestamp unix
.
$ systemctl show --value --timestamp=unix --property=ActiveEnterTimestamp foo.timer
ActiveEnterTimestamp=@1744548379
If you're running systemd older than v247, bypass systemctl and query the properties directly via D-Bus (the properties themselves were available in all systemd versions):
#!/bin/python3
import dbus
bus = dbus.SystemBus()
manager = bus.get_object("org.freedesktop.systemd1",
"/org/freedesktop/systemd1")
# manager = dbus.Interface(manager, "org.freedesktop.systemd1.Manager")
unit_path = manager.GetUnit("sshd.service",
dbus_interface="org.freedesktop.systemd1.Manager")
unit = bus.get_object("org.freedesktop.systemd1",
unit_path)
timestamp_us = unit.Get("org.freedesktop.systemd1.Unit",
"ActiveEnterTimestamp",
dbus_interface="org.freedesktop.DBus.Properties")
timestamp = timestamp_us / 1e6
(pydbus might be more convenient but the legacy dbus-python is more widely available.)
If you want "pure Bash":
res=$(busctl call org.freedesktop.systemd1 \
/org/freedesktop/systemd1 \
org.freedesktop.systemd1.Manager GetUnit \
s "$unit")
if [[ $res =~ ^o\ \"(.+)\"$ ]]; then
obj=${BASH_REMATCH[1]}
res=$(busctl get-property org.freedesktop.systemd1 \
"$obj" \
org.freedesktop.systemd1.Unit \
ActiveEnterTimestamp)
if [[ $res =~ ^t\ (.+)$ ]]; then
timestamp_us=${BASH_REMATCH[1]}
timestamp=$(( timestamp_us / 1000000 ))
fi
fi
(It's not really "pure Bash" but I'm not about to implement the D-Bus binary protocol in Bash.)
what is the formula expressing relationship of *Timestamp and *TimestampMonotonic values?
They're independent timestamps, both obtained via clock_gettime() from two clocks kept by the kernel. The "epoch" of the monotonic clock is the time the system has booted; however, there is no formula for relationship between them, as the monotonic timestamp does not advance while the system is suspended whereas the wall clock does.
The monotonic clock also does not react to manual adjustments of the wall clock – even if wall time jumps back/forward or is delayed/sped up by NTP sync, the monotonic clock continues advancing monotonically (hence the name).
So if the difference between two monotonic timestamps is 10, that always means 10 seconds of "system running" time, which cannot be said about the difference between two wall-clock Unix epoch timestamps.
Use lsclocks
or Python time.clock_gettime()
to compare the values.