Рейтинг:2

как проверить, синхронизировано ли системное время с NTP-сервером, не зная, какой ntp-клиент используется в продукте?

флаг cn

как проверить, синхронизировано ли системное время с NTP-сервером, не зная, какой NTP-клиент используется в продукте? Я разрабатываю приложение, которое должно работать как в контейнерах, так и в автономных системах. В моем приложении есть требование обеспечить синхронизацию системного времени, прежде чем оно попытается выполнить определенные операции. Однако нельзя гарантировать доступность пакета NTP/chrony в контейнере, даже если в хост-ОС используется тот или иной клиент NTP.

Поэтому я ищу единый способ узнать, синхронизировано ли системное время или нет?

John Mahowald avatar
флаг cn
Вы ищете портативное решение? Некоторые ответы, которые вы получаете, неверны, например, systemd предназначен только для Linux.
cptMikky avatar
флаг us
Из того, что я прочитал, кажется, что вы действительно хотите убедиться, что системные часы «вовремя», так сказать.Тот факт, что ящик синхронизирован с NTP-сервером, не обязательно означает, что время правильное, а только то, что оно синхронизировано с NTP-сервером. Если вам нужно первое, ваша единственная безопасная ставка — сделать какое-то сравнение смещения времени с надежным источником времени.
Рейтинг:2
флаг cn

Приложения для вычислений общего назначения не могут во всех случаях знать, как работает синхронизация времени на хостах, на которых они работают. В контейнере вы не видите и не можете подключиться к chronyd или ntpd, работающим на хосте, но это прекрасно сохраняет время. Или гостевая виртуальная машина, которая использует синхронизацию времени хоста, также не видна. Еще больше усложняет общий ответ то, что существует больше реализаций NTP, чем вы думаете: chrony, ntp, ntpsec, openntpd, w32tm.

Часто достаточно документального подтверждения важности точного времени.

На некоторых платформах сделать зависимость от запуска ntpd довольно просто. На RHEL, чтобы дождитесь синхронизации времени systemctl включить хрони-ожидание и добавьте в свой системный блок

После=time-sync.target
Требует = time-sync.target

Тем не менее, есть приложения со строгими временными требованиями. Самое требовательное, что я могу придумать, это отметка времени властями, один из которых стандарты требований требуют менее одной секунды компенсации или ничего не может быть выдано. Этот агрессивный ответ подразумевает, что приложение выполняет собственные проверки времени.

Возможно, вы связали клиент SNTP, который проверяет смещения NTP в вашем приложении, с настраиваемыми серверами NTP.Невозможно проверить правильность работы ntpd, но можно проверить корректность смещений независимо от того, как работает синхронизация времени с хостом.

Рейтинг:1
флаг jo

Есть два способа сделать это.

Если контейнер, который вы используете, имеет полную реализацию systemd, то timedatectl программа может сообщить вам, если хост синхронизирован или нет.

Внутреннее управление осуществляется через dbus, который обращается к systemd-timedated демон. Что он делает, так это выполняет системный вызов: adjtimex из которого можно получить данные, указывающие на текущий статус корректировки в ядре (если таковая имеется), которая выполняется.

Следовательно, второй способ сделать это самостоятельно без полной реализации — использовать adjtimex() системный вызов.

Ядро не хочет иметь временные скачки в своих отчетах о времени (или, что еще хуже, время перемещается назад), поэтому оно реализует перекос во времени, который в течение нескольких часов корректирует системное время (это сделано). путем добавления или задержки на несколько миллисекунд в секунду, пока настройка не будет завершена).

adjtimex системный вызов обычно используется системами NTP для изменения текущего перекоса, с которым сталкиваются часы, чтобы заставить их правильно синхронизироваться с истинным источником часов - но его также можно использовать для получения текущего состояния перекоса источника тактового сигнала. Следовательно, это дает вам возможность заглянуть в ядро ​​​​идеи о том, какая синхронизация выполняется (если есть).

справочная страница для adjtimex предоставляет несколько интересных частей, которые относятся к тому, что вы спрашиваете:

       Поле buf.status представляет собой битовую маску, которая используется для установки и/или получения битов состояния, связанных с реализацией NTP. Некоторые биты в маске
       доступны как для чтения, так и для установки, в то время как другие доступны только для чтения.
...
       STA_UNSYNC (чтение-запись)
              Часы не синхронизированы.

и

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
       В случае успеха adjtimex() и ntp_adjtime() возвращают состояние часов; то есть одно из следующих значений:
...
       TIME_ERROR Системные часы не синхронизированы с надежным сервером. Это значение возвращается, когда выполняется любое из следующих условий:

                   * Установлен либо STA_UNSYNC, либо STA_CLOCKERR.

                   * STA_PPSSIGNAL сброшен, и установлено либо STA_PPSFREQ, либо STA_PPSTIME.

                   * Оба параметра STA_PPSTIME и STA_PPSJITTER установлены.

                   * Установлен STA_PPSFREQ и установлен либо STA_PPSWANDER, либо STA_PPSJITTER.

                   Символическое имя TIME_BAD является синонимом TIME_ERROR и предназначено для обратной совместимости.

Таким образом, если у вас нет полноценного контейнера, все равно можно получить эти данные. Я написал простую программу, которая будет получать статус перекоса ядра через adjtimex в С.Вы можете скомпилировать его, например gcc -o timex timex.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ошибка.h>
#include <string.h>

#include <sys/timex.h>

/* Написано для https://serverfault.com/questions/1077601/how-to-check-whether-the-system-time-is-ynchronised-to-ntp-server-without-knowi */

недействительный test_status (
    инт ст) 
{
  если (ст и STA_PLL)
    printf("Цикл фазовой автоподстройки частоты\n");
  если (ст и STA_PPSFREQ)
    printf("Дисциплина частоты пульса в секунду\n");
  если (ст и STA_FLL)
    printf("Временная дисциплина PPS\n");
  если (ст и STA_INS)
    printf("Вставить дополнительную секунду и конец дня\n");
  если (ст и STA_DEL)
    printf("Удалить дополнительную секунду и конец дня\n");
  если (ст и STA_UNSYNC)
    printf("Часы не синхронизированы\n");
  если (ст и STA_FREQHOLD)
    printf("Удерживать частоту\n");
  если (ст и STA_PPSSIGNAL)
    printf("Имеется действительный сигнал PPS\n");
  если (ст и STA_PPSJITTER)
    printf("Превышено дрожание сигнала PPS\n");
  если (ст и STA_PPSWANDER)
    printf("Превышено отклонение сигнала PPS\n");
  если (ст и STA_PPSERROR)
    printf("Ошибка калибровки сигнала PPS\n");
  если (ст и STA_CLOCKERR)
    printf("Аппаратная ошибка часов\n");

  если (ст и STA_NANO)
    printf("Наносекундное разрешение\n");
  еще
    printf("Разрешение в микросекундах\n");

  если (ст и STA_MODE)
    printf("Цикл блокировки частоты\n");
  еще
    printf("Цикл фазовой автоподстройки частоты\n");
}

интервал основной () {
  структура timex tx = {};
  tx.modes = ADJ_OFFSET_SS_READ;
  int ошибка = adjtimex(&tx);

  переключатель (ошибка) {
    Дело 1:
      printf("Ошибка времени: %s\n", strerror(errno));
    сломать;

    случай TIME_WAIT:
      printf("Вторая вставка/удаление завершена\n");
    сломать;

    случай TIME_INS:
      printf("Високосная секунда будет добавлена ​​на следующий день UTC\n");
    сломать;

    случай TIME_DEL:
      printf("Високосная секунда будет удалена в следующий UTC-день\n");
    сломать;

    случай TIME_OOP:
      printf("Выполняется вставка дополнительной секунды\n");
    сломать;

    случай TIME_ERROR:
      printf("Ошибка получения времени\n");
    сломать;

    случай TIME_OK:
      printf("Время в норме\n");
    сломать;

    По умолчанию:
      printf("Время по умолчанию: %x (%d)\n", ошибка, ошибка);
    сломать;
  }

  test_status (tx.статус);
  выход (0);
}

Запуск в системе, которая не синхронизирована:

$ ./timex 
Ошибка получения времени
Часы не синхронизированы
Микросекундное разрешение
Контур фазовой автоподстройки частоты

Запуск в контейнере на том же хосте, который не синхронизирован:

# podman run -v /tmp/timex/timex:/timex docker.io/gammabytehosting/rockylinux /timex
Ошибка получения времени
Часы не синхронизированы
Микросекундное разрешение
Контур фазовой автоподстройки частоты

Установка времени в хост-системе для синхронизации:

# systemctl запустить хронид
# хронические источники
210 Количество источников = 9
Имя MS/IP-адрес Stratum Poll Reach LastRx Последняя выборка               
================================================== ==============================
^* _шлюз 2 6 7 1 +5568нс[-720мс] +/- 32мс
# ./таймекс 
Время ОК
Микросекундное разрешение
Контур фазовой автоподстройки частоты

Выполнение той же программной проверки в контейнере на том же хосте:

# podman run -v /tmp/timex/timex:/timex docker.io/gammabytehosting/rockylinux /timex
Время ОК
Микросекундное разрешение
Контур фазовой автоподстройки частоты

Потенциально существует некоторая проблема с пространствами имен времени, которые я не тестировал (хотя они действительно очень новые), чтобы увидеть, отличаются ли они или уважают adjtimex в отдельном контексте (см. человек 7 time_namespaces), но из того, что я читал, он, вероятно, все еще будет работать - я оставлю это на ваше усмотрение.

Рейтинг:-1
флаг eg

Как проверить, синхронизировано ли системное время с NTP-сервером?

Нет.

В моем приложении есть требование обеспечить синхронизацию системного времени, прежде чем оно попытается выполнить определенные операции.

Приложение не несет ответственности за настройку правильной среды для запуска, это зависит от системы и ее администратора.

Приложения полагаются на дату/время, возвращаемые системой. Является ли это время либо "правильный" или же "неправильный" ; приложение, как правило, не может знать об этом. Он просто будет использовать эту системную дату/время.

Если у вас есть модель клиент-сервер, то было бы хорошо предоставлять полезное сообщение об ошибке всякий раз, когда транзакции будут отклонены из-за (экстремальных) смещений даты/времени.
Обратите внимание, что наличие такого смещения не говорит вам о том, что у клиента неверные часы, или сервер, или и то, и другое.

Matthew Ife avatar
флаг jo
Пользователь запрашивает, возможно ли определить (без проверки реализации NTP), чтобы увидеть, корректируется ли каким-либо образом перекос ядра. Хотя приложение не настраивает среду, хорошее приложение может проверить, что оно находится в правильной среде, тем не менее, не внося никаких изменений.
John Mahowald avatar
флаг cn
Приложение, не контролирующее и не осведомленное об окружающей среде, плохо справится с выводом о том, как работает синхронизация времени. Либо оставьте это на усмотрение администратора ОС хоста, либо более строго определите задействованные программные и/или аппаратные часы.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.