Tento triviální úkol vznikl jednoho pátečního odpoledne a měl zabrat 2-3 minuty času. Obecně jako vždy.
Kolega mě požádal, abych opravil skript na jeho serveru. Udělal jsem to, podal jsem mu to a nechtěně upustil: "Čas je rychlý 5 minut." Nechte server, aby synchronizaci zvládl sám. Uplynula půlhodina, hodina a on stále funěl a tiše nadával.
"Hloupý! – pomyslel jsem si a přepnul na serverovou konzoli – dobře, dám si ještě pár minut pauzu.
Díváme se ntp, rdate, sdwdate není instalován timesyncd zakázáno a neběží.
# 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
Zde si okamžitě všimnu, že hardwarový čas je správný: bude snazší navigovat dále.
První chyba. Sebevědomí
klik-klak...
# 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
Vše je v pořádku, čas je synchronizovaný, systémový čas odpovídá hardwarovému. "Vezmi si to," řekl jsem a vrátil se ke svému podniku.
„Vezmi si co? - rozhořčil se kolega. "Je stejný čas!"
Čím více řešíte typické problémy, tím více se vaše myšlení zamračí a už si nemyslíte, že sté nebo tisící situace bude jiná, ale tentokrát ne.
# 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
Systémový čas je opět špatný.
Pojď to zkusit znovu:
# 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
Udělejme to jinak:
# 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
A tak:
# 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
Čas je nastaven na zlomek sekundy a okamžitě začne znovu „spěchat“.
Zároveň v protokolech v době takové ruční změny vidíme pouze systémové hlášení, že se čas změnil, resp. správným/špatným směrem a občas Probíhá opětovná synchronizace ze 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
zde
# ps afx | grep "[1]187"
1187 ? Ss 0:02 /lib/systemd/systemd --user
V tuto chvíli již bylo nutné hledat příčinu, ale za 18 let administrace si mozek nashromáždil statistiky o „časových“ chybách a ze zvyku opět obviňuje synchronizaci.
Vypneme úplně.
# 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
a v protokolech
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
Probíhá opětovná synchronizace zmizely a jinak jsou klády nedotčené.
Kontrola závěrů tcpdump na portu 123 na všech rozhraních. Nejsou žádné žádosti, ale čas stále utíká.
Chyba dvě. Spěch
Do konce pracovního týdne zbývá hodina a nechce se mi odjíždět na víkend s triviálním nevyřešeným problémem (času v kódu si nevšímejte, článek byl napsán v následujících dnech ).
A opět jsem se místo hledání příčiny začal snažit přijít s vysvětlením výsledku. Říkám „vynalézt“, protože bez ohledu na to, jak logické může být vysvětlení výsledku, je to chybný přístup k řešení problému.
Tento server je streamovací server a převádí DVB-S2 stream na IP. DVB-S stream obsahuje časové značky, takže přijímače, multiplexery, scramblery a televize je často používají k synchronizaci systémových hodin. Ovladače desky DVB-S jsou zabudovány v jádře, takže nejrychlejším způsobem, jak zajistit odstranění toku DVB-S2, je odpojit kabely přicházející z „desek“. Naštěstí je server za zdí, takže budiž.
Samozřejmě, pokud by protokoly obsahovaly to, co by tam mělo být, nestalo by se tak, ale o tom opět na konci článku.
No a když už jsme odstranili všechny satelitní signály, odstraníme i pozemní - zároveň vytáhneme všechny síťové kabely. Server se odřízne od okolního světa a funguje zcela autonomně, ale systémové hodiny stále spěchají.
Pracovní týden je u konce a problém data/času sám o sobě není kritický, takže můžete jít domů, ale tady dělám novou chybu.
Chyba tři. poradci
Nikdy! Nikdy nepokládejte otázky na fórech a obecně specializovaných (a la stackoverflow) stránkách, pokud odpověď na ně vyžaduje více než prostudování první stránky Google a přečtení jedné manuálové stránky.
Pošlou vás zpět do Googlu, přečtou si stejného muže a s oblibou vysvětlí pravidla fóra/stránky, ale nedají vám odpověď.
Zde jsou některé objektivní faktory:
- nikdo kromě vás nemůže znát problém také;
- nikdo nemůže provádět testy za stejných podmínek jako ty
a subjektivní:
- možná neposkytnete všechny podklady pro řešení problému, protože jste již přišli na „správný“ směr a se zaměřením na podstatu problému prezentujete;
- předák (moderátor, staromilec, admin) má vždycky pravdu, když se předák mýlí... no, znáte to...
Pokud jste se při odpovídání na komentáře drželi v mezích cenzurované slovní zásoby, tak máte pevné nervy.
rozhodnutí
Není potřeba rozdělovat úkoly na jednoduché a složité.
Přestáváme spoléhat na své zkušenosti, statistiky, poradce a začínáme „nevysvětlovat“ konečný výsledek, ale důsledně hledat důvod.
Protože někdo nastavuje čas, musí proběhnout odpovídající systémové volání.
Stejně jako v softwarové dokumentaci jsou nejlepšími dokumenty zdroje, tak i při správě systému je v našem případě nejlepším pomocníkem audit auditováno.
Chvilka pochybnostíProšel jsem manu, ale nebyl jsem si úplně jistý, že čas v Linuxu lze pouze nastavit clock_settime и settimeofday, takže pro první test jsem vybral všechna „vhodná“ volání:
# 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
a vyřazení s390_runtime_instr, stime, timerfd_createkterý auditctl nerozpoznal, původně spustil audit ve tvaru:
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
Poté, co jsem se ujistil, že v umístěních protokolů, které mě zajímají, nejsou žádné další protokoly systémová volání Kromě těchto dvou jsem dále používal pouze je.
Spuštění auditu systémového volání clock_settime и settimeofday a zkuste změnit datum:
# auditctl -a exit,always -S clock_settime -S settimeofday && date -s "2019-08-22 12:10:00" && sleep 5 && auditctl -D
Je přidáno pětisekundové zpoždění, takže náš „parazit“ zaručeně opraví čas.
Podívejme se na reportáž:
# 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
Tady vidíme naše datum a pro nás neznámé chkcache_processes. Skončilo to ve výše uvedené zprávě, protože aureport seřadil výstup podle data při převodu z binárního kódu a událost nastala v čase, který jsme nastavili datum -s "2019-08-22 12:10:00".
Kdo ho porodil?
# 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 - byl nalezen náš parazit. Navzdory jeho „škodlivému“ chování není možné odmítnout systém podmíněného přístupu, ale přesto bych to rád věděl oscam, WTF?
Odpověď je rychle nalezena v
#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");
}
Jak roztomile to tady vypadá okomentoval čára Varování...
Zdroj: www.habr.com