Score:2

how to check whether the system time is synchronised to NTP server without knowing the ntp client used in the product?

cn flag

how to check whether the system time is synchronized to NTP server without knowing the NTP client used in the product? I'm developing an application that is expected to run in both containers or standalone systems. My application has a requirement to ensure that the system time is synchronized before it attempts to perform certain operations. However, the availability of NTP/chrony package could not be guaranteed to be available in the container even though one or the other NTP client is used in the host OS.

So I'm looking for a unified way to know whether the system time is synchronized or not?

John Mahowald avatar
cn flag
Are you looking for a portable solution? Some of the answers you are getting are not, for example systemd is Linux only.
cptMikky avatar
us flag
From what I read it seems you actually want to make sure the system clock is "on time", so to speak. The mere fact that a box is synced with an NTP server does not necessarily mean the time is correct, only that it is synced to the NTP server. If you need the former, your only safe bet is to do some kind of time offset comparison against a trusted time source.
Score:2
cn flag

Applications on general purpose compute cannot know in all cases how time sync works on the hosts they run on. In a container, you do not see and cannot connect to the chronyd or ntpd running on the host, yet this keeps time just fine. Or a VM guest that relies on host time sync, also not visible. Further making a general answer difficult, there are more NTP implementations than you might think: chrony, ntp, ntpsec, openntpd, w32tm.

Often documentation of the importance of correct time is sufficient.

On some platforms, making a dependency on an ntpd starting is relatively straight forward. On RHEL, to wait for time sync systemctl enable chrony-wait and add to your systemd unit

After=time-sync.target
Requires=time-sync.target

Yet there are applications with strict time requirements. Most demanding I can think of is time stamping authorities, one of which claims standards require less than one second offset or nothing can be issued. This aggressive of a response implies the application does its own time checks.

Perhaps bundling a SNTP client, which checks NTP offsets in your application, against configurable NTP servers. Cannot check for a proper ntpd running, but can sanity check offsets regardless of how time sync works to the host.

Score:1
jo flag

There is two ways to do this.

If the container you're running has a full systemd implementation, then the timedatectl program can inform you if the host is synchronized or not.

The way that this is internally managed is via dbus which speaks to the systemd-timedated daemon. What it is doing is perfoming a system call: adjtimex from which its possible to get data back indicating the current status of the adjustment in the kernel (if any) that is being done.

Hence, the second way to do this yourself without a full implementation is by using the adjtimex() system call.

The kernel doesn't want to have time jumps in its reporting of the time (or worse, time travelling backwards) as such it implements a skew in the time which over a the course of a few hours would correct a systems time (its done by adding or delaying a few milliseconds per second until the adjustment is complete).

The adjtimex system call is typically used by NTP systems to change the current skew the clock is facing to get it to synchronize correctly with a true clock source -- but it can also be used to fetch the current status of the skew of the clock source. Hence it gives you the ability to peek into the kernels idea of what sync is being done (if any).

The man page for adjtimex provides a couple of interesting portions that pertain to what you are asking:

       The  buf.status  field  is a bit mask that is used to set and/or retrieve status bits associated with the NTP implementation.  Some bits in the mask
       are both readable and settable, while others are read-only.
...
       STA_UNSYNC (read-write)
              Clock unsynchronized.

and

RETURN VALUE
       On success, adjtimex() and ntp_adjtime() return the clock state; that is, one of the following values:
...
       TIME_ERROR  The system clock is not synchronized to a reliable server.  This value is returned when any of the following holds true:

                   *  Either STA_UNSYNC or STA_CLOCKERR is set.

                   *  STA_PPSSIGNAL is clear and either STA_PPSFREQ or STA_PPSTIME is set.

                   *  STA_PPSTIME and STA_PPSJITTER are both set.

                   *  STA_PPSFREQ is set and either STA_PPSWANDER or STA_PPSJITTER is set.

                   The symbolic name TIME_BAD is a synonym for TIME_ERROR, provided for backward compatibility.

As such, if you dont have a fully fledged container, its possible to still get this data. I wrote a simple program that will fetch the status of the kernels skew via adjtimex in C. You can compile it for example gcc -o timex timex.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#include <sys/timex.h>

/* Written for https://serverfault.com/questions/1077601/how-to-check-whether-the-system-time-is-synchronised-to-ntp-server-without-knowi */

void test_status(
    int st) 
{
  if (st & STA_PLL)
    printf("Phase locked loop\n");
  if (st & STA_PPSFREQ)
    printf("Pulse per second frequency discipline\n");
  if (st & STA_FLL)
    printf("PPS Time discipline\n");
  if (st & STA_INS)
    printf("Insert leap second and end-of-day\n");
  if (st & STA_DEL)
    printf("Delete leap second and end-of-day\n");
  if (st & STA_UNSYNC)
    printf("Clock is not syncronized\n");
  if (st & STA_FREQHOLD)
    printf("Hold frequency\n");
  if (st & STA_PPSSIGNAL)
    printf("Valid PPS signal is present\n");
  if (st & STA_PPSJITTER)
    printf("PPS signal jitter exceeded\n");
  if (st & STA_PPSWANDER)
    printf("PPS Signal wander exceeded\n");
  if (st & STA_PPSERROR)
    printf("PPS signal calibration error\n");
  if (st & STA_CLOCKERR)
    printf("Clock hardware fault\n");

  if (st & STA_NANO)
    printf("Nanosecond resolution\n");
  else
    printf("Microsecond resolution\n");

  if (st & STA_MODE)
    printf("Frequency locked loop\n");
  else
    printf("Phase locked loop\n");
}

int main() {
  struct timex tx = {};
  tx.modes = ADJ_OFFSET_SS_READ;
  int err = adjtimex(&tx);

  switch(err) {
    case -1:
      printf("Time error: %s\n", strerror(errno));
    break;

    case TIME_WAIT:
      printf("Leap second insert/delete completed\n");
    break;

    case TIME_INS:
      printf("Leap second to be added next UTC day\n");
    break;

    case TIME_DEL:
      printf("Leap second to be deleted next UTC day\n");
    break;

    case TIME_OOP:
      printf("Leap second insertion in progress\n");
    break;

    case TIME_ERROR:
      printf("Error getting time\n");
    break;

    case TIME_OK:
      printf("Time OK\n");
    break;

    default:
      printf("Time default: %x (%d)\n", err, err);
    break;
  }

  test_status(tx.status);
  exit(0);
}

Running on a system that is not syncronised:

$ ./timex 
Error getting time
Clock is not syncronized
Microsecond resolution
Phase locked loop

Running in a container on the same host that is not synchronised:

# podman run -v /tmp/timex/timex:/timex  docker.io/gammabytehosting/rockylinux /timex
Error getting time
Clock is not syncronized
Microsecond resolution
Phase locked loop

Setting the time in the host system to be synchronised:

# systemctl start chronyd
# chronyc sources
210 Number of sources = 9
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* _gateway            2   6     7     1  +5568ns[ -720ms] +/-   32ms
# ./timex 
Time OK
Microsecond resolution
Phase locked loop

Performing the same programmatic check in the container on the same host:

# podman run -v /tmp/timex/timex:/timex  docker.io/gammabytehosting/rockylinux /timex
Time OK
Microsecond resolution
Phase locked loop

There is potentially some issue with time namespaces that I haven't tested (they are really very new though) to see if they differ or honour adjtimex in a separate context (see man 7 time_namespaces) but from what I've read its probably still going to work -- I'd leave that for you to determine.

Score:-1
eg flag

How to check whether the system time is synchronised to a NTP server?

There isn't.

My application has a requirement to ensure that the system time is synchronized before it attempts to perform certain operations

It is not a responsibility of the application to set up the correct environment to run, that is up to the system and its administrator.

Applications rely on the date/time returned by the system. Whether that time is either "correct" or "wrong" ; the application generally has no way of knowing that. It will simply use that system date/time.

If you have a client-server model then providing a useful error message whenever transactions are going to be rejected because of (extreme) date/time offsets would be good.
Note that the existence of such an off-set does not tell you if the client is on an incorrect clock, or the server, or both.

Matthew Ife avatar
jo flag
What the user is requesting is whether or not its possible to identify (without checking for NTP implementations) to see if the kernel is having its skew adjusted somehow. Whilst the application doens't setup the environment, a good application might check it is in the correct environment nonetheless without making any changes.
John Mahowald avatar
cn flag
An application not in control and unaware of the environment will do a poor job of inferring how time sync is working. Either leave this up to the host OS administrator, or more strictly define the software and/or hardware clocks involved.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.