Cu cât sarcina este mai simplă, cu atât greșesc mai des

Cu cât sarcina este mai simplă, cu atât greșesc mai des

Această sarcină banală a apărut într-o vineri după-amiază și ar fi trebuit să dureze 2-3 minute. În general, ca întotdeauna.

Un coleg mi-a cerut să repar scriptul pe serverul său. Am făcut-o, i-am dat-o și, din neatenție, am scăpat: „Timpul este rapid cu 5 minute”. Lăsați serverul să se ocupe de sincronizarea în sine. A trecut o jumătate de oră, o oră, iar el încă pufăia și înjură în liniște.

"Prost! — M-am gândit, trecând la consola serverului — bine, voi mai face o pauză de câteva minute.”

Să vedem ntp, rdate, sdwdate nu este instalat timesyncd dezactivat și nu rulează.

# 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

Aici voi observa imediat că ora hardware este corectă: va fi mai ușor să navigați mai departe.

De aici a început seria greșelilor.

Prima greseala. Încredere în sine

Click-clac...

# 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

Totul este bine, ora este sincronizată, ora sistemului se potrivește cu cea hardware. „Ia-o”, am spus și m-am întors la afacerea mea.

„Ia ce? - s-a indignat colegul. „Este același timp!”

Cu cât rezolvi mai mult problemele tipice, cu atât gândirea ta devine mai sclipitoare și nu mai crezi că situația a suta sau a miilea va fi diferită, dar nu de data aceasta.

# 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

Ora sistemului este greșită din nou.

Hai sa incercam din nou:

# 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

Să o facem altfel:

# 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

Dar cam asa:

# 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

Timpul este setat pentru o fracțiune de secundă și începe imediat să se „grabă” din nou.

Totodată, în jurnalele, la momentul unei astfel de modificări manuale, vedem doar rapoarte de sistem că ora s-a schimbat, respectiv, în direcția corectă/greșită și ocazional Resincronizare de la 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

aici

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

În acest moment, era deja necesar să se caute motivul, dar peste 18 ani de administrare, creierul a acumulat statistici privind erorile „de timp” și, din obișnuință, dă vina din nou pe sincronizare.
Să o oprim complet.

# 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

iar în jurnalele

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

Resincronizare au dispărut și în rest buștenii sunt curați.

Verificarea concluziilor tcpdump pe portul 123 pe toate interfețele. Nu există solicitări, dar timpul încă fuge.

Eroare doi. Te grabesti

A mai ramas o ora pana la sfarsitul saptamanii de lucru, si nu vreau sa plec in weekend cu o banala problema nerezolvata (nu fi atent la ora din cod, articolul a fost scris in zilele urmatoare ).
Și iar aici, în loc să caut motivul, am început să încerc să vin cu o explicație pentru rezultat. Spun „inventează” pentru că oricât de logică ar fi explicația rezultatului, este o abordare greșită a rezolvării problemei.

Acest server este un server de streaming și convertește fluxul DVB-S2 în IP. Fluxul DVB-S conține marcaje de timp, astfel încât receptoarele, multiplexoarele, scramblerele și televizoarele le folosesc adesea pentru a sincroniza ceasul sistemului. Driverele plăcii DVB-S sunt încorporate în nucleu, așa că cea mai rapidă modalitate de a vă asigura că fluxul DVB-S2 este îndepărtat este deconectarea cablurilor care vin de la „plăci”. Din fericire, serverul este în spatele peretelui, așa să fie.

Desigur, dacă jurnalele ar fi conținut ceea ce ar trebui să fie acolo, acest lucru nu s-ar fi întâmplat, dar mai multe despre asta, din nou, la sfârșitul articolului.

Ei bine, deoarece am eliminat deja toate semnalele de satelit, le vom elimina și pe cele terestre - în același timp scoatem toate cablurile de rețea. Serverul este separat de lumea exterioară și funcționează complet autonom, dar ceasul sistemului este încă grăbit.

Săptămâna de lucru s-a încheiat, iar problema dată/ora în sine nu este critică, așa că puteți merge acasă, dar aici fac o nouă greșeală.

Eroare trei. Consilieri

Nu! Nu puneți niciodată întrebări pe forumuri și site-uri generale specializate (a la stackoverflow) dacă răspunsul la acesta necesită mai mult decât studierea primei pagini Google și citirea unei pagini de manual.

Vă vor trimite înapoi la Google, vor citi același om și vă vor explica popular regulile forumului/site-ului, dar nu vă vor da un răspuns.

Iată câțiva factori obiectivi:

  • nimeni, cu excepția dvs., nu poate cunoaște problema;
  • nimeni nu poate efectua teste în aceleași condiții ca ale dumneavoastră

si subiectiv:

  • este posibil să nu oferiți toate contribuțiile pentru rezolvarea problemei, deoarece ați venit deja cu direcția „corectă” și prezentați esența problemei concentrându-vă asupra acesteia;
  • maistrul (moderator, old-timer, admin) are intotdeauna dreptate, daca maistrul greseste... pai, stii...

Dacă, atunci când răspunzi la comentarii, ai rămas în limitele vocabularului cenzurat, atunci ai nervi puternici.

decizie

Nu este nevoie să împărțiți sarcinile în simple și complexe.

Încetăm să ne bazăm pe experiența noastră, statisticile, consilierii și începem să nu „explicam” rezultatul final, ci să căutăm în mod constant motivul.

Deoarece cineva setează ora, trebuie să aibă loc apelul de sistem corespunzător.

Așa cum în documentația software, cele mai bune documente sunt sursele, la fel în administrarea sistemului cel mai bun asistent este auditul, în cazul nostru auditd.

Un moment de îndoialăAm trecut prin mana, dar nu eram pe deplin sigur că ora în Linux poate fi setată doar clock_settime и setare de zi, așa că pentru primul test am ales toate apelurile „potrivite”:

# 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

și aruncarea s390_runtime_instr, stime, timerfd_create, care auditctl nu l-a recunoscut, a lansat inițial un audit sub forma:

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

După ce m-am asigurat că nu există alte jurnale în locațiile de jurnal care mă interesează syscall-uri Pe lângă acestea două, le-am folosit în continuare.

Rularea unui audit al apelurilor de sistem clock_settime и setare de zi si incearca sa schimbi data:

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

Se adaugă o întârziere de cinci secunde, astfel încât „parazitul” nostru să fie garantat să corecteze timpul.

Sa vedem raportul:

# 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

Aici ne vedem data și necunoscut de noi chkcache_proceses. S-a ajuns în raportul de mai sus, deoarece aureport a sortat rezultatul după dată la conversia din binar, iar evenimentul a avut loc la ora stabilită. data -s "2019-08-22 12:10:00".
Cine l-a născut?

# 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 - parazitul nostru a fost găsit. În ciuda comportamentului său „răușitor”, este imposibil să refuz sistemul de acces condiționat, dar aș dori totuși să știu oscam, WTF?

Răspunsul se găsește rapid în codurile sursă:

#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");
}

Ce drăguț arată aici comentat linia avertizare...

Sursa: www.habr.com

Adauga un comentariu