como verificar se a hora do sistema está sincronizada com o servidor NTP sem conhecer o cliente NTP utilizado no produto?

como verificar se a hora do sistema está sincronizada com o servidor NTP sem conhecer o cliente NTP utilizado no produto?

como verificar se a hora do sistema está sincronizada com o servidor NTP sem conhecer o cliente NTP utilizado no produto? Estou desenvolvendo um aplicativo que deverá ser executado em contêineres ou em sistemas autônomos. Meu aplicativo tem um requisito para garantir que a hora do sistema esteja sincronizada antes de tentar executar determinadas operações. No entanto, não é possível garantir que a disponibilidade do pacote NTP/chrony esteja disponível no contêiner, mesmo que um ou outro cliente NTP seja usado no sistema operacional host.

Então estou procurando uma maneira unificada de saber se a hora do sistema está sincronizada ou não?

Responder1

Os aplicativos de computação de uso geral não podem saber em todos os casos como funciona a sincronização de horário nos hosts em que são executados. Em um contêiner, você não vê e não pode se conectar ao chronyd ou ntpd em execução no host, mas isso mantém o tempo correto. Ou um convidado da VM que depende da sincronização do horário do host, também não visível. Tornando ainda mais difícil uma resposta geral, há mais implementações de NTP do que você imagina: chrony, ntp, ntpsec, openntpd, w32tm.

Freqüentemente, a documentação da importância do horário correto é suficiente.

Em algumas plataformas, criar dependência de uma inicialização ntpd é relativamente simples. No RHEL, paraaguarde a sincronização do horário systemctl enable chrony-waite adicione à sua unidade systemd

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

No entanto, existem aplicações com requisitos de tempo rigorosos. O mais exigente que posso imaginar são as autoridades de carimbo de data/hora,um dos quais os padrões de sinistros exigem menos de um segundo de compensação ou nada pode ser emitido. Essa resposta agressiva implica que o aplicativo faça suas próprias verificações de tempo.

Talvez agrupando um cliente SNTP, que verifica as compensações de NTP em seu aplicativo, em relação a servidores NTP configuráveis. Não é possível verificar se o ntpd está em execução adequado, mas a sanidade pode verificar as compensações, independentemente de como a sincronização de tempo funciona para o host.

Responder2

Existem duas maneiras de fazer isso.

Se o contêiner que você está executando tiver uma implementação completa do systemd, o timedatectlprograma poderá informar se o host está sincronizado ou não.

A maneira como isso é gerenciado internamente é via dbus, que se comunica com o systemd-timedateddaemon. O que ele está fazendo é realizar uma chamada de sistema: adjtimexa partir da qual é possível recuperar dados indicando o status atual do ajuste no kernel (se houver) que está sendo feito.

Portanto, a segunda maneira de fazer isso sem uma implementação completa é usando a adjtimex()chamada do sistema.

O kernel não quer ter saltos no tempo em seu relatório de tempo (ou pior, viajar no tempo para trás), como tal, ele implementa uma distorção no tempo que ao longo de algumas horas corrigiria a hora do sistema (está feito adicionando ou atrasando alguns milissegundos por segundo até que o ajuste seja concluído).

A adjtimexchamada do sistema é normalmente usada por sistemas NTP para alterar a distorção atual que o relógio está enfrentando para sincronizá-lo corretamente com uma fonte de relógio verdadeira -mastambém pode ser usado para buscar o status atual da distorção da fonte do relógio. Conseqüentemente, você pode dar uma olhada na ideia do kernel sobre qual sincronização está sendo feita (se houver).

A página de manual adjtimexfornece algumas partes interessantes relacionadas ao que você está perguntando:

       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.

e

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.

Dessa forma, se você não tiver um contêiner completo, ainda é possível obter esses dados. Eu escrevi um programa simples que irá buscar o status dos kernels distorcidos adjtimexem C. Você pode compilá-lo por exemplogcc -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);
}

Executando em um sistema que não está sincronizado:

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

Executando em um contêiner no mesmo host que não está sincronizado:

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

Configurando a hora no sistema host a ser sincronizada:

# 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

Executando a mesma verificação programática no contêiner no mesmo host:

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

Há potencialmente algum problema com os namespaces de tempo que eu não testei (eles são realmente muito novos) para ver se eles diferem ou honram adjtimexem um contexto separado (veja man 7 time_namespaces), mas pelo que li provavelmente ainda vai funcionar - - Eu deixaria isso para você determinar.

Responder3

Como verificar se a hora do sistema está sincronizada com um servidor NTP?

Não há.

Meu aplicativo tem um requisito para garantir que a hora do sistema esteja sincronizada antes de tentar executar determinadas operações

Não é responsabilidade da aplicação configurar o ambiente correto para rodar, isso cabe ao sistema e seu administrador.

Os aplicativos dependem da data/hora retornada pelo sistema. Quer esse tempo seja"correto"ou"errado"; o aplicativo geralmente não tem como saber disso. Ele simplesmente usará a data/hora do sistema.

Se você tiver um modelo cliente-servidor, seria bom fornecer uma mensagem de erro útil sempre que as transações forem rejeitadas devido a compensações (extremas) de data/hora.
Observe que a existência de tal deslocamento não informa se o cliente está em um relógio incorreto, ou o servidor, ou ambos.

informação relacionada