Колку е поедноставна задачата, толку почесто правам грешки

Колку е поедноставна задачата, толку почесто правам грешки

Оваа тривијална задача настана едно петок попладне и требаше да одземе 2-3 минути време. Во принцип, како и секогаш.

Еден колега ме замоли да ја поправам скриптата на неговиот сервер. Го направив тоа, му го подадов и ненамерно ми падна: „Времето е брзо 5 минути“. Дозволете серверот сам да се справи со синхронизацијата. Помина половина час, еден час, а тој се уште се надува и тивко пцуеше.

„Глупаво! – Си помислив, префрлајќи се на серверската конзола – во ред, ќе паузирам уште неколку минути.

Ајде да видиме ntp, rdate, sdwdate Не е инсталирано временски оневозможено и не работи.

# timedatectl
      Local time: Sun 2019-08-25 20:44:39 +03
  Universal time: Sun 2019-08-25 17:44:39 UTC
        RTC time: Sun 2019-08-25 17:39:52
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

Овде веднаш ќе забележам дека хардверското време е точно: ќе биде полесно да се движите понатаму.

Тука започна серијата грешки.

Првата грешка. Самодоверба

Клик-клак...

# systemctl enable systemd-timesyncd.service && systemctl start systemd-timesyncd.service && ntpdate 0.ru.pool.ntp.org && timedatectl set-ntp on && timedatectl
25 Aug 21:00:10 ntpdate[28114]: adjust time server 195.210.189.106 offset -249.015251 sec
      Local time: Sun 2019-08-25 21:00:10 +03
  Universal time: Sun 2019-08-25 18:00:10 UTC
        RTC time: Sun 2019-08-25 18:00:10
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a

Сè е во ред, времето е синхронизирано, системското време се совпаѓа со хардверското. „Земи го“, реков и се вратив на мојот бизнис.

„Земи што? - се налути колегата. „Исто време е!“

Колку повеќе решавате типични проблеми, толку повеќе вашето размислување станува трепка и повеќе не мислите дека стотата или илјадитата ситуација ќе биде поинаква, но не овојпат.

# timedatectl
      Local time: Sun 2019-08-25 21:09:15 +03
  Universal time: Sun 2019-08-25 18:09:15 UTC
        RTC time: Sun 2019-08-25 18:05:04
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

Системското време повторно е погрешно.

Да се ​​обидеме повторно:

# ntpdate 0.ru.pool.ntp.org && timedatectl && sleep 1 && timedatectl
25 Aug 21:07:37 ntpdate[30350]: step time server 89.175.20.7 offset -249.220828 sec
      Local time: Sun 2019-08-25 21:07:37 +03
  Universal time: Sun 2019-08-25 18:07:37 UTC
        RTC time: Sun 2019-08-25 18:07:37
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:11:46 +03
  Universal time: Sun 2019-08-25 18:11:46 UTC
        RTC time: Sun 2019-08-25 18:07:37
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

Ајде да го направиме поинаку:

# date -s "2019-08-25 21:10:30" && date && sleep 1 && timedatectl
Sun Aug 25 21:10:30 +03 2019
Sun Aug 25 21:10:30 +03 2019
      Local time: Sun 2019-08-25 21:14:36 +03
  Universal time: Sun 2019-08-25 18:14:36 UTC
        RTC time: Sun 2019-08-25 18:10:30
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

И вака:

# hwclock --hctosys && timedatectl && sleep 1 && timedatectl
      Local time: Sun 2019-08-25 21:11:31 +03
  Universal time: Sun 2019-08-25 18:11:31 UTC
        RTC time: Sun 2019-08-25 18:11:31
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:15:36 +03
  Universal time: Sun 2019-08-25 18:15:36 UTC
        RTC time: Sun 2019-08-25 18:11:32
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

Времето е поставено за дел од секундата и веднаш почнува повторно да „брза“.

Во исто време, во дневниците, во моментот на таква рачна промена, гледаме само системски извештаи дека времето се променило, соодветно, во правилна/погрешна насока и повремено Ресинхронизирање од systemd-timesyncd.

Aug 25 21:18:51 wisi systemd[1]: Time has been changed
Aug 25 21:18:51 wisi systemd-timesyncd[29258]: System time changed. Resyncing.
Aug 25 21:18:51 wisi systemd[1187]: Time has been changed
Aug 25 21:18:51 wisi systemd[1]: Time has been changed
Aug 25 21:18:51 wisi systemd[1187]: Time has been changed

тука

# ps afx | grep "[1]187"
 1187 ?        Ss     0:02 /lib/systemd/systemd --user

Во овој момент, веќе беше неопходно да се бара причината, но во текот на 18 години администрација, мозокот акумулираше статистика за „временски“ грешки и, по навика, повторно ја обвинува синхронизацијата.
Ајде да го исклучиме целосно.

# timedatectl set-ntp off && systemctl stop systemd-timesyncd.service
# hwclock --hctosys && timedatectl && sleep 1 && timedatectl
      Local time: Sun 2019-08-25 21:25:40 +03
  Universal time: Sun 2019-08-25 18:25:40 UTC
        RTC time: Sun 2019-08-25 18:25:40
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:29:31 +03
  Universal time: Sun 2019-08-25 18:29:31 UTC
        RTC time: Sun 2019-08-25 18:25:41
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

и во дневниците

Aug 25 21:25:40 wisi systemd[1]: Time has been changed
Aug 25 21:25:40 wisi systemd[1187]: Time has been changed
Aug 25 21:29:30 wisi systemd[1]: Time has been changed
Aug 25 21:29:30 wisi systemd[1187]: Time has been changed

Ресинхронизирање исчезна, а инаку трупците се недопрени.

Проверка на заклучоците tcpdump на портата 123 на сите интерфејси. Нема барања, но времето се уште бега.

Грешка два. Брзање

Останува уште еден час до крајот на работната недела, а јас не сакам да заминам за викенд со тривијален нерешен проблем (не обрнувајте внимание на времето во шифрата, статијата е напишана во следните денови ).
И тука повторно, наместо да ја барам причината, почнав да се обидувам да дојдам до објаснување за резултатот. Велам „измисли“ затоа што колку и да е логично објаснувањето за резултатот, тоа е погрешен пристап за решавање на проблемот.

Овој сервер е сервер за стриминг и го конвертира преносот на DVB-S2 во IP. Преносот DVB-S содржи временски ознаки, така што ресиверите, мултиплексерите, скромлерите и телевизорите често ги користат за да го синхронизираат системскиот часовник. Двигателите на таблата DVB-S се вградени во кернелот, така што најбрзиот начин да се осигури дека потокот DVB-S2 е отстранет е да ги исклучите каблите што доаѓаат од „плочите“. За среќа, серверот е зад ѕидот, така нека биде.

Се разбира, ако дневниците го содржеа она што треба да го има, ова немаше да се случи, но повеќе за тоа, повторно, на крајот од статијата.

Па, бидејќи веќе ги отстранивме сите сателитски сигнали, ќе ги отстраниме и копнените - во исто време ги извлекуваме сите мрежни кабли. Серверот станува отсечен од надворешниот свет и работи целосно автономно, но системскиот часовник сè уште брза.

Работната недела заврши, а самото прашање за датум/време не е критично, па можете само да си одите дома, но еве правам нова грешка.

Грешка трета. Советници

Никогаш! Никогаш не поставувајте прашања на форуми и општи специјализирани (a la stackoverflow) сајтови ако одговорот бара повеќе од проучување на првата страница на Google и читање на една страница за човек.

Ќе те вратат на Гугл, ќе го читаат истиот човек и популарно ќе ти ги објаснат правилата на форумот/страницата, но нема да ти дадат одговор.

Еве неколку објективни фактори:

  • никој освен тебе не може да го знае проблемот;
  • никој не може да спроведе тестови под исти услови како твоите

и субјективно:

  • можеби нема да го дадете целиот придонес за решавање на проблемот, бидејќи веќе сте дошле до „вистинската“ насока и ја презентирате суштината на прашањето фокусирајќи се на тоа;
  • надзорникот (модератор, олдтајмер, админ) е секогаш во право, ако греши надзорникот... добро, знаеш...

Ако кога одговаравте на коментари сте останале во границите на цензуриран речник, тогаш имате силни нерви.

Решение

Нема потреба да се делат задачите на едноставни и сложени.

Престануваме да се потпираме на нашето искуство, статистика, советници и почнуваме да не го „објаснуваме“ крајниот резултат, туку доследно да ја бараме причината.

Бидејќи некој го поставува времето, мора да се случи соодветниот системски повик.

Како што во софтверската документација најдобри документи се изворите, така и во системската администрација најдобар асистент е ревизијата, во нашиот случај ревидирани.

Момент на сомнежПоминав низ мана, но не бев сосема сигурен дека времето во Linux може да се постави само часовник_поставување време и време на денот, така што за првиот тест ги избрав сите „погодни“ повици:

# man syscalls | col | grep -F '(2)' | grep -vE '(:|;)' | grep -E '(time|date|clock)' | sed "s/(2).*//" | xargs -I SYSCALL echo "-S SYSCALL " | xargs echo
-S adjtimex -S clock_adjtime -S clock_getres -S clock_gettime -S clock_nanosleep -S clock_settime -S futimesat -S getitimer -S gettimeofday -S mq_timedreceive -S mq_timedsend -S rt_sigtimedwait -S s390_runtime_instr -S setitimer -S settimeofday -S stime -S time -S timer_create -S timer_delete -S timer_getoverrun -S timer_gettime -S timer_settime -S timerfd_create -S timerfd_gettime -S timerfd_settime -S times -S utime -S utimensat -S utimes

и отфрлање s390_runtime_instr, stime, timerfd_create, кои ревизија не го препозна, првично започна ревизија во форма:

auditctl -a exit,always -S adjtimex -S clock_adjtime -S clock_getres -S clock_nanosleep -S clock_settime -S futimesat -S getitimer -S gettimeofday -S mq_timedreceive -S mq_timedsend -S rt_sigtimedwait -S semtimedop -S setitimer -S settimeofday -S time -S timer_create -S timer_delete -S timer_getoverrun -S timer_gettime -S timer_settime -S timerfd_gettime -S timerfd_settime -S times -S utime -S utimensat -S utimes

Откако ќе се уверам дека нема други дневници на локациите за дневници што ме интересираат syscals Покрај овие две, само ги користев понатаму.

Водење ревизија на системски повик часовник_поставување време и време на денот и обидете се да го промените датумот:

# auditctl -a exit,always -S clock_settime -S settimeofday && date -s "2019-08-22 12:10:00" && sleep 5 && auditctl -D

Додадено е доцнење од пет секунди, така што нашиот „паразит“ гарантирано ќе го поправи времето.

Да го погледнеме извештајот:

# aureport -s -i

Syscall Report
=======================================
# date time syscall pid comm auid event
=======================================
Warning - freq is non-zero and incremental flushing not selected.
1. 08/22/2019 12:10:00 settimeofday 3088 chkcache_proces root 479630
2. 08/26/2019 09:37:06 clock_settime 1538 date root 479629

Еве ги гледаме нашите датум и за нас непознати chkcache_processes. Заврши во извештајот погоре затоа што aureport го подреди излезот по датум при конвертирање од бинарно, а настанот се случи во времето кога го поставивме датум -s "2019-08-22 12:10:00".
Кој го роди?

# ausearch -sc settimeofday --comm "chkcache_proces"
----
time->Thu Aug 22 12:10:00 2019
type=PROCTITLE msg=audit(1566465000.000:479630): proctitle="/usr/local/bin/oscam"
type=SYSCALL msg=audit(1566465000.000:479630): arch=c000003e syscall=164 success=yes exit=0 a0=7fde0dfc6e60 a1=0 a2=136cf a3=713ba56 items=0 ppid=3081 pid=3088 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts20 ses=68149 comm="chkcache_proces" exe="/usr/local/bin/oscam" key=(null)

/usr/local/bin/oscam - пронајден е нашиот паразит. И покрај неговото „злонамерно“ однесување, невозможно е да се одбие системот за условен пристап, но сепак би сакал да знам осмам, WTF?

Одговорот брзо се наоѓа во извори:

#if defined(CLOCKFIX)
if (tv.tv_sec > lasttime.tv_sec || (tv.tv_sec == lasttime.tv_sec && tv.tv_usec >= lasttime.tv_usec)) // check for time issues!
{
  lasttime = tv; // register this valid time
}
  else
{
  tv = lasttime;
  settimeofday(&tv, NULL); // set time back to last known valid time
  //fprintf(stderr, "*** WARNING: BAD TIME AFFECTING WHOLE OSCAM ECM HANDLING, SYSTEMTIME SET TO LAST KNOWN VALID TIME **** n");
}

Колку слатко изгледа овде коментираше линија предупредување...

Извор: www.habr.com

Додадете коментар