Как узнать во время запуска системы, когда системное время станет правильным из NTP

У меня есть малина Pi, в которой работает Raspbian (производная Debian), которая записывает температуры в реальном времени. Как часть этого, мне нужны часы с точностью до нескольких секунд. В обычной работе, когда сервер работает, я понимаю, что Raspberry Pi регулярно подключается по сети к серверу NTP, чтобы убедиться, что локальные часы достаточно близки к правильному времени. Этот уровень точности подходит для моего приложения. У малины Pi нет часов с батарейным питанием, чтобы поддерживать время, когда сервер выключается или отключается, поэтому, когда он загружается, системное время неверно, пока оно не установит подключение к Интернету и не получит правильное время через NTP.

Где я нашел проблему, когда происходит перебои в подаче электроэнергии, а малина Pi отключена в течение некоторого периода времени без питания, затем снова активируется (например, 30 минут). Pi boots, мое приложение запускается и снова начинает регистрировать температуры, но часы на Pi не правильны, поэтому записывают температуры с неправильной меткой времени. Кажется, он каким-то образом сохранил последнее известное время и отбирает оттуда (он не возвращается к эпохе, когда он перезапускается). В конце концов, когда локальная сеть, в которой находится Pi, восстанавливает и восстанавливает подключение к Интернету, Pi исправит свое время (через NTP), но до этого у меня есть неточные отметки времени, которые записываются.

Я пытаюсь выяснить, каков наилучший способ решения этой проблемы?

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

Я хочу, чтобы мое приложение откладывало температуру записи, пока не узнаю, что время было точно извлечено из сети, но я даже не знаю, как определить это состояние. Кто-нибудь знает, как узнать, когда время обновлено с сервера NTP, и теперь это правильно?

Мое приложение запускается при запуске скрипта при запуске.

Любые другие идеи по решению этой проблемы?

7 Solutions collect form web for “Как узнать во время запуска системы, когда системное время станет правильным из NTP”

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

Итак, что может быть проще всего, – это иметь скрипт, который запускает вашу программу измерения температуры, сначала вызывать ntpdate или эквивалент, которая устанавливает дату или число символов в зависимости от того, насколько далека от полученного значения. Поэтому ntpdate не нарушает работу, если часы уже установлены близко к ntp например, если вы перезапустите этот сценарий без перезагрузки.

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

По умолчанию ntpd будет только сканировать часы, если это будет меньше 1000 секунд, но реализация Debian обеспечивает флаг -g чтобы переопределить ограничение и разрешить переход из любого смещения. (Это хорошо.)

Кроме того, флаг -x будет принудительно поворачивать время, а не набирать интервалы до 600 секунд; вам не нужен этот набор. (Дефолт Debian не устанавливает этот флаг, что является хорошим.)

Проверьте /etc/default/ntp , который должен иметь только эту строку, устанавливая флаги:

 NTPD_OPTS='-g' 

Другой вариант может состоять в том, чтобы проанализировать вывод «ntpq -c peers», чтобы следить за тем, чтобы слой удалялся от 16.

Ваш NTP-клиент также является NTP-сервером, и он может сообщать о своем текущем статусе своим клиентам.

На самом деле я использую chrony а не ntpd , и когда я спрашиваю его о текущем статусе, он говорит следующее:

 [axa@enyo ~]$ chronyc tracking Reference ID : pqst (xxx.yyy.zzz) Stratum : 4 Ref time (UTC) : Sun May 31 22:35:34 2015 System time : 0.000630264 seconds slow of NTP time Last offset : +0.000047504 seconds RMS offset : 0.023269517 seconds Frequency : 6.462 ppm slow Residual freq : -0.023 ppm Skew : 0.225 ppm Root delay : 0.031594 seconds Root dispersion : 0.025155 seconds Update interval : 1035.3 seconds Leap status : Normal 

В поле «Системное время» ваш процесс может решить, достаточно ли часы. Я почти уверен, что вы можете прочитать эти значения напрямую, не анализируя вывод команды, предназначенной для использования человеком, но я не знаю деталей.

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

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

Ваша система экономит время (в /etc/fake-hwclock.data ), которое должно ежечасно обновляться с cron задачи cron . Результатом этого является то, что записанное время всегда будет до фактического времени (к моменту отключения плюс 0-1 час).

Конечным результатом этого является то, что у вас будет файл журнала с регулярными временами и возможный «пробел» во время отключения питания. Когда ntp пинает, он будет корректировать время, поэтому у вас будет «пробел» для коррекции.

Возможно, что после отключения время может появиться назад (если есть записи журнала после того, как cron сохраняет время).

Все, что вам нужно сделать, – это обработать файл журнала, обнаружить изменения пробелов / времени и исправить файл. Чтобы упростить taks, я мог бы записывать отчет в сообщение о запуске процесса регистрации.

Сказав все это, я бы просто получил RTC (всего несколько долларов на eBay), который будет держать время в течение многих лет с использованием батареи за 1 доллар, что я и использую на своем Pi.

Проверьте программу ntp-wait которая поставляется с NTP. Вы запускаете его, он ждет, пока ваши часы не будут синхронизированы, и выйдет. (Или он в конечном итоге сдается и выходит с ошибкой.) Вы можете использовать его, чтобы ваш скрипт не запускался до тех пор, пока часы не будут синхронизированы.

Вы также можете запустить что-то вроде ntpq -p или ntpq -c rv и проанализировать вывод, чтобы проверить статус ваших часов. Действительно, ntp-wait – это короткий скрипт Perl, который делает именно это.

То, что я решил, что я хочу в своем решении, – это функция, которая вернет обещание, которое разрешилось, когда системное время было точным. Затем я мог бы вызвать эту функцию при запуске, и мы получим ее обратную связь, чтобы узнать, когда снова начать регистрировать температуры. Для этого я решил использовать ntpClient, чтобы получить точное время и сравнить его с местным системным временем. Когда они находятся в пределах желаемой точности, я могу решить обещание. Когда это не так, я устанавливаю таймер и перепроверяю время, продолжая до тех пор, пока в результате локальное системное время не станет достаточно точным. Таким образом, далеко все это прекрасно справилось через несколько отключений электроэнергии (именно там была обнаружена проблема с неточным временем).

Вот код, который я использовал:

 const Promise = require('bluebird'); const ntpClient = Promise.promisifyAll(require('ntp-client')); const log = require('./log'); function Decay(startT, maxT, decayAmount, decayTimes) { // startT is initial delay (eg 5 seconds) // maxT is the max delay this ever returns (eg 5 minutes) // decayAmount is how much to decay when a threshold is crossed (eg increase by 0.5) // decayTimes is how many invocations should trigger a decayAmount (eg every 5 times) // example: var d = new Decay(5000, 5*60*1000, .5, 5); // each 5 seconds, to a max of 5 minutes, getting 50% longer every 5 invocations // make sure decayTimes is at least 1 and not negative decayTimes = Math.max(decayTimes, 1); var num = 0; var currentDelay = startT; var start = Date.now(); this.val = function() { var elapsed = Date.now() - start; // if evenly divisible by decayTimes, then bump the increment if (num !== 0 && num % decayTimes === 0) { currentDelay = Math.min(Math.round((1 + decayAmount) * currentDelay), maxT); } ++num; return currentDelay; }; } function checkSystemTime(precision) { precision = precision || 5000; return ntpClient.getNetworkTimeAsync("pool.ntp.org", 123).then(function(ntpTime) { return Math.abs(ntpTime.getTime() - Date.now()) <= precision; }); } function waitForAccurateSystemTime(precision, howLong) { var start = Date.now(); // retry starts every 5 seconds, repeats 5 times, then increases by 50% // up until longest retry time of once every 15 minutes var decay = new Decay(5000, 15*60*1000, .5, 5); var errCntr = 0; var inaccurateCntr = 0; function logRetries() { // only log anything if there were more than five consecutive errors if (errCntr > 5 || inaccurateCntr > 0) { log(7, "Time synchronization issue, errCntr = " + errCntr + ", inaccurateCntr = " + inaccurateCntr); } } return new Promise(function(resolve, reject) { function check() { checkSystemTime(precision).then(function(accurate) { if (accurate) { resolve(true); } else { ++inaccurateCntr; again(); } }, again); } function again() { ++errCntr; if (errCntr == 10) { // only log once here that we're in a retry loop on 10th retry // final logging will be done later log(7, "In retry loop waiting for system time to agree with ntp server time"); } // if we're only supposed to go for a certain amount of time, then check to see // if we exceeded that amount of time. If not, set timer for next decay() value. if (!howLong || Date.now() - start <= howLong) { setTimeout(check, decay.val()); } else { var err = "timeout waiting for accurate system time"; log(7, err); reject(err); } } check(); }).then(function(result) { logRetries(); return result; }).catch(function(err) { logRetries(); throw err; }); } module.exports = { checkSystemTime: checkSystemTime, waitForAccurateSystemTime: waitForAccurateSystemTime, Decay: Decay }; 

И я использую это следующим образом:

 const validTime = require("./valid-time"); validTime.waitForAccurateSystemTime(2 * 60 * 1000, 0).then({ // start operation here that requires accurate system time }).catch({ // abort process, no accurate system time could be found }); 
  • Как я могу взаимодействовать с домашним маршрутизатором через устройство в локальной сети с помощью ssh?
  • Несоответствие конфигурации звуковой карты между pi и root
  • Несколько (объединить) звуковые карты USB с Alsa + Jack + Pure Data
  • Не удается подключиться к серверу OpenVPN
  • ifplugd (lo): сбой выполнения программы, возвращаемое значение равно 1
  • Получить имя устройства в сети
  • Предотвратите системную запись от строк состояния регистрации до tty
  • Как я могу проверить RUNLEVEL из сценария bash на Rasbpian?
  • VPN SoftEther - я не могу получить доступ к VPN-серверу непосредственно с подключенного к VPN устройства
  • Разница между ppp0 vs wwan0
  • Обновите / обновите Debian и пропустите любые взаимодействия
  • Interesting Posts

    Невозможно выполнить поиск флажков на странице руководства qalter?

    iptables и ssh

    Как восстановить раздел ext3 после работы с измененным размером?

    Как я могу избежать восклицательного знака в переменной среды PS1?

    Почему yum-builddep не предоставил зависимости для установки rpm?

    Статическая привязка util-linux – кросс-компиляция (вместо этого создает динамически связанные файлы)

    Как установить и запустить python и базу данных через busybox

    RHEL Satellite Server 5.5 и EPEL Sync Issue (gzip vs. bz2 с manifest.xml)

    Получение «Ошибка протокола» при попытке создания символической ссылки в Docker

    Как администратор системы может заблокировать доступ к файлу в течение 24 часов?

    Какова функция / точка "config.sub"

    Я случайно вышел из vim с: x! ~, И теперь моя ~ появляется по другому пути

    Самая быстрая среда рабочего стола для Mint 14

    Как извлекать строки по словам в определенном месте, а не в столбце?

    Как добавить Mageia 2 на свой USB-накопитель YUMI MultiBoot?

    Linux и Unix - лучшая ОС в мире.