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

kill $ (ps -ef | grep '[s] earch-string' | sed -re 's / [[: blank:]] + / \ t / g' | cut -f2)

  1. ps - ef : получает список процессов с аргументами
  2. grep : фильтры для записи, которую вы хотите, [] не позволяют grep находить себя.
  3. sed -re 's / [[: blank:]] + / \ t / g' : преобразует пространство в одну табуляцию
  4. cut -f2 : извлекает поле pid

Примечание: ps не очень переносим, ​​есть один для posix, один для bsd, один для system-v. Кажется, что Gnu пытается быть совместимым со всеми.

5
01.06.2015, 20:49
2 ответа

Я решил, что мне нужна в моем решении функция, которая возвращала бы промис, который разрешался, когда системное время было точным. Затем я мог бы вызвать эту функцию при запуске и использовать ее обратную связь, чтобы узнать, когда снова начать запись температуры. Для этого я решил использовать 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 (e.g. 5 seconds)
    // maxT is the max delay this ever returns (e.g. 5 minutes)
    // decayAmount is how much to decay when a threshold is crossed (e.g. increase by 0.5)
    // decayTimes is how many invocations should trigger a decayAmount (e.g. 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
});
0
27.01.2020, 20:33

Это чрезвычайно полезная ветка, освещающая реальную существующую проблему (, которая часто не решается или решается ужасно, ненадежным образом ), что влияет на удобство использования и затраты на обслуживание миллионов «ТВ» системы (скоро миллиарды ). Несколько хороших советов по ntp выше, NTP полезен, но иногда опаздывает на вечеринку:

DX=`date +%s.%4N`
DB=`awk -v DX=$DX '{printf "%.0f",DX-$1}' /proc/uptime`
c=$(( $c+1 ))
echo "${DX} DB=$DB $$ $c $MSG"

Метод Марселла :вычитание времени безотказной работы(первого поля /proc/uptime)из даты unix($DX )= (время загрузки БД )(может теоретически измениться на 1 из-за округления, хотя никогда такого не видел ). Недавно записанный пример filename=date...$DB.$$.$c.myapp.gpg:

2019-05-16.200713.1558037061.1207.6.myapp.gpg
2019-05-16.201348.1558037061.1207.7.myapp.gpg

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

Примечание. :$$ после загрузки, вероятно, будет другим, и $DB тоже будет другим, счетчик $c подтверждает непрерывность.

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

Непрофессионально внедрять хрупкие системы или позволять проблемам развиваться вместо того, чтобы сдерживать их. (1 подсистема работает неправильно, например.сеть или NTP => другие подсистемы также зависают => такие методы, применяемые в больших системах, создают правильный рецепт для циклических зависимостей, ненадежных систем или полного краха системы в самый неподходящий момент, который мы можем себе представить ). Непрофессионально добавлять ненужные зависимости (= позволить кому-то другому, например. это решают админы, мы программисты и нам все равно ). Например. требуется, чтобы сеть, шлюз и серверы времени всегда были доступны сразу после загрузки, а RTC устанавливался и обслуживался (, заменяя батареи, возможно, в десятках или сотнях устройств ). Да, конечно, надежная сеть и системы NTP приветствуются. Батарея RTC в любом гаджете обычно больше боли, чем пользы.

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

Возможны дальнейшие улучшения (также, перенос /bin/sh на.py или.c или... ), конечно. Обычно регистрация в UTC, отображение в локализованной форме TZ является хорошей идеей (местное -время может вернуться назад, что иногда может вызвать проблемы ). Bash великолепен, но следует избегать синтаксиса bash, если его легко заставить хорошо работать с оболочкой /bin/sh dash или busybox... избегайте шумового слова bash «функция».

0
27.01.2020, 20:33

Теги

Похожие вопросы