Plus la tâche est simple, plus je me trompe souvent

image

Cette tâche insignifiante est survenue un des jours du vendredi et aurait dû prendre 2-3 minutes. En général, comme toujours.

Un collègue m'a demandé de corriger le script sur son serveur. Il l'a fait, l'a remis à lui et l'a laissé tomber par inadvertance: "Le temps presse dans 5 minutes." Son serveur, même s'il comprend la synchronisation. Une demi-heure, une heure s'est écoulée, et il souffle et jure doucement.

«Muddle! - J'ai pensé, en passant à la console du serveur - eh bien, je m'en vais encore quelques minutes. »

Nous regardons, ntp, rdate, sdwdate ne sont pas installés, timesyncd est désactivé et ne fonctionne pas.

# 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 

Ici, je note tout de suite que l'heure du matériel est correcte: il sera plus facile de naviguer plus loin.

De là, une série d'erreurs a commencé.

Première erreur. Confiance en soi


Klats-klats ...

 # 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 

Tout va bien, le temps a été synchronisé, le système coïncide avec le matériel. «Prends-le», laissai-je tomber et retournai à mon entreprise.

"Que retirer?" - le collègue s'est indigné. "Le vieux temps!"

Plus vous résolvez des problèmes typiques, plus votre réflexion démarre et vous ne pensez pas que la centième ou la millième situation sera différente, mais pas cette fois.

 # 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 

L'heure système est à nouveau incorrecte.

Essayons encore:

 # 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 

Faisons-le différemment:

 # 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 

Et donc:

 # 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 

Le temps est fixé pour une fraction de seconde, puis recommence à "se précipiter".

De plus, dans les journaux, au moment d'un tel changement manuel, nous ne voyons que les rapports du système indiquant que l'heure a changé, respectivement, dans le bon / mauvais sens et parfois la resynchronisation de 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 

ici

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

À ce stade, il était déjà nécessaire de rechercher la cause, mais le cerveau pendant 18 ans d'administration a développé des statistiques d'erreurs de «temps» et par habitude blâme à nouveau la synchronisation.
Éteignez-le complètement.

 # 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 

et dans les journaux

 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 

La resynchronisation a disparu et le reste des journaux est vierge.

Nous vérifions les sorties tcpdump sur le 123ème port sur toutes les interfaces. Il n'y a pas de demandes, mais le temps file aussi.

La deuxième erreur. Hâte


Il reste une heure avant la fin de la semaine de travail, mais vous ne voulez pas partir pour le week-end avec une mauvaise tâche (ne faites pas attention à l'heure dans le code, l'article a été écrit les jours suivants).
Et là encore, au lieu de chercher une raison, j'ai commencé à essayer de trouver une explication au résultat. Je dis «inventer», car quelle que soit la logique des explications du résultat, il s'agit d'une approche erronée pour résoudre le problème.

Ce serveur est en streaming et convertit le flux DVB-S2 en IP. Il y a des horodatages dans le flux DVB-S, donc les récepteurs, multiplexeurs, brouilleurs et téléviseurs les utilisent souvent pour synchroniser l'horloge du système. Les pilotes pour les cartes DVB-S sont compilés dans le noyau, donc le moyen le plus rapide de garantir un flux DVB-S2 propre est de déconnecter les câbles provenant des "plaques". Heureusement, le serveur est derrière le mur, qu'il en soit ainsi.

Bien sûr, si les journaux avaient ce qui devrait être là, cela ne serait pas arrivé, mais plus à ce sujet, encore une fois, à la fin de l'article.

Eh bien, puisque nous avons déjà supprimé tous les signaux satellites, nous supprimerons également ceux terrestres - en cours de route, nous retirerons tous les câbles réseau. Le serveur est coupé du monde extérieur et fonctionne de manière complètement autonome, mais l'horloge système est toujours pressée.

La semaine de travail est terminée et la question de la date et de l'heure n'est pas critique, vous pouvez donc simplement rentrer chez vous, mais ici je fais une nouvelle erreur.

La troisième erreur. Conseillers


Jamais! Ne posez jamais de questions sur des forums et des sites généralement spécialisés (à la stackoverflow) si la réponse nécessite plus que d'étudier l'émission de la première page de Google et de lire une page de man'a.

Vous serez renvoyé sur google, lirez le même homme et expliquerez les règles du forum / site, mais vous ne répondrez pas.

Il y a deux facteurs objectifs:

  • personne sauf vous ne peut également connaître le problème;
  • personne ne peut tester dans les mêmes conditions que vous

et subjective:
  • vous ne donnerez peut-être pas tous les éléments pour résoudre le problème, parce que vous avez déjà trouvé la «bonne» direction et énoncé l'essence du problème en vous appuyant dessus;
  • contremaître (modérateur, old-timer, admin) a toujours raison si le contremaître a tort ... eh bien, vous savez ...

Si en réponse à des commentaires vous êtes resté dans le cadre du vocabulaire de la censure, alors vous avez les nerfs forts.

Solution


Pas besoin de diviser les tâches en simples et complexes.

Nous cessons de nous fier à notre expérience, à nos statistiques, à nos conseillers et commençons non pas à «expliquer» le résultat final, mais à chercher constamment la raison.

Une fois que quelqu'un a réglé l'heure, un appel système approprié doit se produire.

Comme dans la documentation des logiciels, les meilleurs quais sont les sources, donc en administration système le meilleur assistant est l'audit, dans notre cas auditd .

Moment de doute
J'ai parcouru le Mans, mais je n'étais pas complètement sûr que l'horloge sous Linux ne puisse être réglée que par clock_settime et settimeofday , donc pour le premier test, j'ai sélectionné tous les appels «appropriés»:

 # 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 

et la suppression de s390_runtime_instr, stime, timerfd_create , que auditctl n'a pas reconnu, a initialement démarré l'audit sous la forme:

 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 

Après m'être assuré qu'à la place des logs qui m'intéressent, il n'y a pas d'autres syscalls que ces deux là, alors je les ai utilisés uniquement.

Nous commençons l'audit des appels système clock_settime et settimeofday et essayons de changer la date:

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

Un délai de cinq secondes a été ajouté afin que notre «parasite» soit garanti de corriger l'heure.

Nous regardons le rapport:

 # 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 

Ici, nous voyons notre date et inconnue pour nous chkcache_proces . Il s'est avéré être dans le rapport ci-dessus, car aureport a trié la sortie par date lors de la conversion à partir de la vue binaire, et l'événement s'est produit au moment où nous avons défini la date -s "2019-08-22 12:10:00" .
Qui lui a donné naissance?

 # 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 - notre parasite a été trouvé. Malgré son comportement "malveillant", il est impossible d'abandonner le système d'accès conditionnel, mais je voudrais quand même savoir, oscam , WTF?

La réponse se trouve rapidement dans la source :

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

Comme la ligne d' avertissement commentée est belle ici ...

Source: https://habr.com/ru/post/fr464951/


All Articles