3

I am writing a data logging python script and I would like it to find out if the system clock has been synchronized via NTP recently, and if not, to attempt to cause it to happen before proceeding.

Starting from this answer, I've found that for the status

os.system('sudo service ntp status')

will display the results on the console, but I don't know how I can get the python script to see if ntp is active or not, since this call returns only 0.

I could always just force a reset even if not needed using

os.system('sudo service ntp stop')
os.system('sudo ntpd -gq')
os.system('sudo service ntp start')

but it seems like a bad idea to do that if it wasn't necessary.

edit: using Raspbian GNU/Linux 8 (jessie)

Question: How can I test the status and then conditionally force a synchronization only if needed?

This answer suggests the package ntplib https://pypi.python.org/pypi/ntplib/ but I'm not sure if this is advisable or not, so I thought I'd ask before installing and running it, and I'd still have to guess the status by comparing the results to the system clock and deciding if the agreement were good enough or not. I'd still like to know if ntp is active and that it believes the synchronization is close.

6
  • You don't say what OS, but Stretch doesn't use ntpd
    – Milliways
    Commented Mar 11, 2018 at 22:57
  • "Raspbian 4.4.21-v7+" is meaningless - it is basically the kernel version /etc/os-release will show release, but you should tag your question with OS
    – Milliways
    Commented Mar 11, 2018 at 23:18
  • @Milliways thanks, cat returns Raspbian GNU/Linux 8 (jessie)
    – uhoh
    Commented Mar 11, 2018 at 23:56
  • @Fabian loaded and disabled. Once enabled, does this only induce synchronization, or can I use it to check the status by calling within a python script using os.system()?
    – uhoh
    Commented Mar 12, 2018 at 0:01
  • lsb_release -irc works nicely as well.
    – uhoh
    Commented Mar 12, 2018 at 0:19

1 Answer 1

2

This type of system information on Linux is often available through D-Bus so I listed all of the D-Bus connections with time in them:

pi@raspberrypi:~ $ busctl | grep time
:1.1                                   359 systemd-timesyn systemd-timesync :1.1          systemd-timesyncd.service -          -                  
org.freedesktop.timedate1                - -               -                (activatable) -                         -         
org.freedesktop.timesync1              359 systemd-timesyn systemd-timesync :1.1          systemd-timesyncd.service -          -          

And I can then do introspection on them to find methods, properties and their values:

Firstly .timedate1:

pi@raspberrypi:~ $ busctl introspect org.freedesktop.timedate1 /org/freedesktop/timedate1
NAME                                TYPE      SIGNATURE RESULT/VALUE     FLAGS
org.freedesktop.DBus.Introspectable interface -         -                -
.Introspect                         method    -         s                -
org.freedesktop.DBus.Peer           interface -         -                -
.GetMachineId                       method    -         s                -
.Ping                               method    -         -                -
org.freedesktop.DBus.Properties     interface -         -                -
.Get                                method    ss        v                -
.GetAll                             method    s         a{sv}            -
.Set                                method    ssv       -                -
.PropertiesChanged                  signal    sa{sv}as  -                -
org.freedesktop.timedate1           interface -         -                -
.ListTimezones                      method    -         as               -
.SetLocalRTC                        method    bbb       -                -
.SetNTP                             method    bb        -                -
.SetTime                            method    xbb       -                -
.SetTimezone                        method    sb        -                -
.CanNTP                             property  b         true             -
.LocalRTC                           property  b         false            emits-change
.NTP                                property  b         true             emits-change
.NTPSynchronized                    property  b         true             -
.RTCTimeUSec                        property  t         0                -
.TimeUSec                           property  t         1601112272495265 -
.Timezone                           property  s         "Europe/London"  emits-change

And then on .timesync1:

pi@raspberrypi:~ $ busctl introspect org.freedesktop.timesync1 /org/freedesktop/timesync1
NAME                                TYPE      SIGNATURE          RESULT/VALUE                             FLAGS
org.freedesktop.DBus.Introspectable interface -                  -                                        -
.Introspect                         method    -                  s                                        -
org.freedesktop.DBus.Peer           interface -                  -                                        -
.GetMachineId                       method    -                  s                                        -
.Ping                               method    -                  -                                        -
org.freedesktop.DBus.Properties     interface -                  -                                        -
.Get                                method    ss                 v                                        -
.GetAll                             method    s                  a{sv}                                    -
.Set                                method    ssv                -                                        -
.PropertiesChanged                  signal    sa{sv}as           -                                        -
org.freedesktop.timesync1.Manager   interface -                  -                                        -
.FallbackNTPServers                 property  as                 4 "0.debian.pool.ntp.org" "1.debian.poo… const
.Frequency                          property  x                  -9162                                    -
.LinkNTPServers                     property  as                 0                                        -
.NTPMessage                         property  (uuuuittayttttbtt) 0 4 4 2 -21 137 14465 4 129 215 32 239 … emits-c
.PollIntervalMaxUSec                property  t                  2048000000                               const
.PollIntervalMinUSec                property  t                  32000000                                 const
.PollIntervalUSec                   property  t                  2048000000                               -
.RootDistanceMaxUSec                property  t                  5000000                                  const
.ServerAddress                      property  (iay)              2 4 129 215 160 240                      -
.ServerName                         property  s                  "2.debian.pool.ntp.org"                  -
.SystemNTPServers                   property  as                 0                                        const

Looking at the outputs, I think timedate1 is the one that will give you the information you require.

To access this information from Python, I find the pydbus library to be very helpful. Here is an example of doing that:

(venv) pi@raspberrypi:~/stack_overflow $ python3
Python 3.7.3 (default, Dec 20 2019, 18:57:59) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pydbus
>>> timedated = pydbus.SystemBus().get(".timedate1")
>>> dir(timedated)
['CanNTP', 'Get', 'GetAll', 'GetMachineId', 'Introspect', 'ListTimezones', 'LocalRTC', 'NTP', 'NTPSynchronized', 'Ping', 'PropertiesChanged', 'RTCTimeUSec', 'Set', 'SetLocalRTC', 'SetNTP', 'SetTime', 'SetTimezone', 'TimeUSec', 'Timezone', '_Introspect', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_bus', '_bus_name', '_object', '_path', 'onPropertiesChanged']
>>> timedated.NTPSynchronized  # Example of access properties
True
>>> timedated.ListTimezones()  # Example of accessing methods
['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', 'Africa/Algiers', 'Africa/Asmara', 'Africa/Bamako', 'Afr...

And for completeness, here are the OS details of the system I ran on:

pi@raspberrypi:~ $ cat /etc/os-release 
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
1
  • 1
    Wow, thank you for the answer!I will go round up my Pi and give this a try.
    – uhoh
    Commented Sep 26, 2020 at 11:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.